All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.otto.edison.mongo.AbstractMongoRepository Maven / Gradle / Ivy

There is a newer version: 3.4.1
Show newest version
package de.otto.edison.mongo;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.FindOneAndReplaceOptions;
import com.mongodb.client.result.DeleteResult;
import org.bson.Document;
import org.bson.conversions.Bson;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Optional;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.ReturnDocument.AFTER;
import static java.util.Objects.isNull;
import static java.util.Optional.ofNullable;

public abstract class AbstractMongoRepository {

    protected static final String ID = "_id";
    protected static final String ETAG = "etag";

    @PostConstruct
    public void postConstruct() {
        ensureIndexes();
    }

    public Optional findOne(final K key) {
        return ofNullable(collection()
                .find(byId(key))
                .map(this::decode)
                .first());
    }

    public List findAll() {
        return collection()
                .find()
                .map(this::decode)
                .into(new ArrayList<>());
    }

    public List findAll(int skip, int limit) {
        return collection()
                .find()
                .skip(skip)
                .limit(limit)
                .map(this::decode)
                .into(new ArrayList<>());
    }

    public V createOrUpdate(final V value) {
        final K key = keyOf(value);
        final Document existing = collection().find(byId(key)).first();
        Document doc = encode(value);
        if (existing != null) {
            collection().replaceOne(byId(key), doc);
        } else {
            collection().insertOne(doc);
        }
        return decode(doc);
    }

    public V create(final V value) {
        Document doc = encode(value);
        collection().insertOne(doc);
        return decode(doc);
    }

    public void update(final V value) {
        final K key = keyOf(value);
        collection().replaceOne(byId(key), encode(value));
    }

    public void updateIfMatch(final V value, final String eTag) {
        Bson query = and(eq(AbstractMongoRepository.ID, keyOf(value)), eq(ETAG, eTag));

        Document updatedETaggable = collection().findOneAndReplace(query, encode(value), new FindOneAndReplaceOptions().returnDocument(AFTER));
        if (isNull(updatedETaggable)) {
            Optional findById = findOne(keyOf(value));
            if (findById.isPresent()) {
                throw new ConcurrentModificationException("Entity concurrently modified: " + keyOf(value));
            }

            throw new NotFoundException("Entity does not exist: " + keyOf(value));
        }
    }

    public long size() {
        return collection().count();
    }

    public DeleteResult delete(final K key) {
        return collection().deleteOne(byId(key));
    }

    public DeleteResult deleteAll() {
        return collection().deleteMany(matchAll());
    }

    protected Document byId(final K key) {
        return key != null ? new Document(ID, key.toString()) : new Document();
    }

    protected Document matchAll() {
        return new Document();
    }

    protected abstract MongoCollection collection();

    protected abstract K keyOf(final V value);

    protected abstract Document encode(final V value);

    protected abstract V decode(final Document document);

    protected abstract void ensureIndexes();
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy