driver-legacy/src/main/com/mongodb/DBCollection.java
public DBObject findAndModify(final DBObject query, final DBCollectionFindAndModifyOptions options) {
        notNull("query", query);
        notNull("options", options);
        WriteConcern optionsWriteConcern = options.getWriteConcern();
        WriteConcern writeConcern = optionsWriteConcern != null ? optionsWriteConcern : getWriteConcern();
        WriteOperation<DBObject> operation;
        if (options.isRemove()) {
            operation = new FindAndDeleteOperation<DBObject>(getNamespace(), writeConcern, retryWrites, objectCodec)
                        .filter(wrapAllowNull(query))
                        .projection(wrapAllowNull(options.getProjection()))
                        .sort(wrapAllowNull(options.getSort()))
                        .maxTime(options.getMaxTime(MILLISECONDS), MILLISECONDS)
                        .collation(options.getCollation());
        } else {
            DBObject update = options.getUpdate();
            if (update == null) {
                throw new IllegalArgumentException("update can not be null unless it's a remove");
            }
            if (!update.keySet().isEmpty() && update.keySet().iterator().next().charAt(0) == '$') {
                operation = new FindAndUpdateOperation<DBObject>(getNamespace(), writeConcern, retryWrites, objectCodec,
                        wrap(update))
                        .filter(wrap(query))
                        .projection(wrapAllowNull(options.getProjection()))
                        .sort(wrapAllowNull(options.getSort()))
                        .returnOriginal(!options.returnNew())
                        .upsert(options.isUpsert())
                        .maxTime(options.getMaxTime(MILLISECONDS), MILLISECONDS)
                        .bypassDocumentValidation(options.getBypassDocumentValidation())
                        .collation(options.getCollation())
                        .arrayFilters(wrapAllowNull(options.getArrayFilters(), (Encoder<DBObject>) null));
            } else {
                operation = new FindAndReplaceOperation<DBObject>(getNamespace(), writeConcern, retryWrites, objectCodec,
                        wrap(update))
                        .filter(wrap(query))
                        .projection(wrapAllowNull(options.getProjection()))
                        .sort(wrapAllowNull(options.getSort()))
                        .returnOriginal(!options.returnNew())
                        .upsert(options.isUpsert())
                        .maxTime(options.getMaxTime(MILLISECONDS), MILLISECONDS)
                        .bypassDocumentValidation(options.getBypassDocumentValidation())
                        .collation(options.getCollation());
            }
        }

        try {
            return executor.execute(operation, getReadConcern());
        } catch (MongoWriteConcernException e) {
            throw createWriteConcernException(e);
        }
    }
public DBObject findAndModify(final DBObject query, final DBCollectionFindAndModifyOptions options) {
        notNull("query", query);
        notNull("options", options);
        WriteConcern optionsWriteConcern = options.getWriteConcern();
        WriteConcern writeConcern = optionsWriteConcern != null ? optionsWriteConcern : getWriteConcern();
        WriteOperation<DBObject> operation;
        if (options.isRemove()) {
            operation = new FindAndDeleteOperation<DBObject>(getNamespace(), writeConcern, retryWrites, objectCodec)
                        .filter(wrapAllowNull(query))
                        .projection(wrapAllowNull(options.getProjection()))
                        .sort(wrapAllowNull(options.getSort()))
                        .maxTime(options.getMaxTime(MILLISECONDS), MILLISECONDS)
                        .collation(options.getCollation());
        } else {
            DBObject update = options.getUpdate();
            if (update == null) {
                throw new IllegalArgumentException("update can not be null unless it's a remove");
            }
            if (!update.keySet().isEmpty() && update.keySet().iterator().next().charAt(0) == '$') {
                operation = new FindAndUpdateOperation<DBObject>(getNamespace(), writeConcern, retryWrites, objectCodec,
                        wrap(update))
                        .filter(wrap(query))
                        .projection(wrapAllowNull(options.getProjection()))
                        .sort(wrapAllowNull(options.getSort()))
                        .returnOriginal(!options.returnNew())
                        .upsert(options.isUpsert())
                        .maxTime(options.getMaxTime(MILLISECONDS), MILLISECONDS)
                        .bypassDocumentValidation(options.getBypassDocumentValidation())
                        .collation(options.getCollation())
                        .arrayFilters(wrapAllowNull(options.getArrayFilters(), (Encoder<DBObject>) null));
            } else {
                operation = new FindAndReplaceOperation<DBObject>(getNamespace(), writeConcern, retryWrites, objectCodec,
                        wrap(update))
                        .filter(wrap(query))
                        .projection(wrapAllowNull(options.getProjection()))
                        .sort(wrapAllowNull(options.getSort()))
                        .returnOriginal(!options.returnNew())
                        .upsert(options.isUpsert())
                        .maxTime(options.getMaxTime(MILLISECONDS), MILLISECONDS)
                        .bypassDocumentValidation(options.getBypassDocumentValidation())
                        .collation(options.getCollation());
            }
        }

        try {
            return executor.execute(operation, getReadConcern());
        } catch (MongoWriteConcernException e) {
            throw createWriteConcernException(e);
        }
    }
Atomically modify and return a single document. By default, the returned document does not include the modifications made on the
update.

@param query    specifies the selection criteria for the modification
@param options  the options regarding the find and modify operation
@return the document as it was before the modifications, unless {@code oprtions.returnNew} is true, in which case it returns the
document after the changes were made
@throws WriteConcernException if the write failed due some other failure specific to the update command
@throws MongoException if the operation failed for some other reason
@mongodb.driver.manual reference/command/findAndModify/ Find and Modify
@since 3.4