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

com.mastfrog.asyncpromises.mongo.QueryBuilderImpl Maven / Gradle / Ivy

There is a newer version: 2.9.7
Show newest version
/*
 * The MIT License
 *
 * Copyright 2015 Tim Boudreau.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.mastfrog.asyncpromises.mongo;

import com.mastfrog.asyncpromises.AsyncPromise;
import com.mastfrog.asyncpromises.Logic;
import com.mastfrog.asyncpromises.PromiseContext;
import com.mastfrog.asyncpromises.SimpleLogic;
import com.mastfrog.asyncpromises.Trigger;
import com.mongodb.client.result.UpdateResult;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.bson.Document;
import org.bson.conversions.Bson;

/**
 *
 * @author Tim Boudreau
 */
class QueryBuilderImpl implements QueryBuilder {

    private final Map equal = new HashMap<>();
    private final Map in = new HashMap<>();
    private final Map greaterThan = new HashMap<>();
    private final Map lessThan = new HashMap<>();
    private final Map greaterThanOrEqual = new HashMap<>();
    private final Map lessThanOrEqual = new HashMap<>();
    private final Map elemMatch = new HashMap<>();
    private final Factory factory;

    QueryBuilderImpl(Factory factory) {
        this.factory = factory;
    }

    static  QueryBuilder create() {
        return new QueryBuilderImpl<>(new BsonFactory());
    }

    static  QueryBuilderImpl> create(CollectionPromises promises) {
        return new QueryBuilderImpl<>(new FindFactory<>(promises));
    }

    static  QueryBuilderImpl> createForCount(CollectionPromises promises) {
        return new QueryBuilderImpl<>(new CountFactory(promises));
    }

    static  QueryBuilderImpl>> createForFindAndModify(CollectionPromises promises) {
        return new QueryBuilderImpl<>(new FindAndModifyOneFactory<>(promises));
    }

    static  QueryBuilder>>> createForUpdate(CollectionPromises promises) {
        return new QueryBuilderImpl<>(new UpdateFactory<>(promises));
    }

    static  QueryBuilderImpl>>> createForBulkWrite(BulkWriteBuilder builder) {
        return new QueryBuilderImpl<>(new BulkWriteUpdateFactory<>(builder));
    }

    static  QueryBuilderImpl, T>> createForReplace(CollectionPromises promises) {
        return new QueryBuilderImpl<>(new ReplaceFactory<>(promises));
    }

    static class BsonFactory implements Factory {

        @Override
        public Document create(Document document) {
            return document;
        }
    }

    static class UpdateFactory implements Factory>>> {

        private final CollectionPromises promises;

        public UpdateFactory(CollectionPromises promises) {
            this.promises = promises;
        }

        @Override
        public ModificationBuilder>> create(final Document query) {
            return new ModificationBuilderImpl<>(new ModificationBuilderImpl.Factory>>() {

                @Override
                public UpdateBuilder> build(final Document modification) {
                    return new UpdateBuilderImpl<>(new UpdateBuilderImpl.Factory>() {

                        @Override
                        public AsyncPromise updateMany(UpdateBuilderImpl builder) {
                            return AsyncPromise.create(new SimpleLogic() {

                                @Override
                                public void run(Void data, Trigger next) throws Exception {
                                    next.trigger(query, null);
                                }
                            }).then(promises.updateMany(modification, builder.opts));
                        }

                        @Override
                        public AsyncPromise updateOne(UpdateBuilderImpl builder) {
                            return AsyncPromise.create(new SimpleLogic() {

                                @Override
                                public void run(Void data, Trigger next) throws Exception {
                                    next.trigger(query, null);
                                }
                            }).then(promises.updateOne(modification));
                        }
                    }).modification(modification);
                }
            });
        }
    }

    static class BulkWriteUpdateFactory implements Factory>>> {

        private final BulkWriteBuilder builder;

        public BulkWriteUpdateFactory(BulkWriteBuilder builder) {
            this.builder = builder;
        }

        @Override
        public ModificationBuilder>> create(final Document query) {
            return new ModificationBuilderImpl<>(new ModificationBuilderImpl.Factory>>() {

                @Override
                public UpdateBuilder> build(final Document modification) {
                    return new UpdateBuilderImpl<>(new UpdateBuilderImpl.Factory>() {

                        @Override
                        public BulkWriteBuilder updateMany(UpdateBuilderImpl bldr) {
                            builder.updateMany(query, modification, bldr.opts);
                            return builder;
                        }

                        @Override
                        public BulkWriteBuilder updateOne(UpdateBuilderImpl bldr) {
                            builder.updateOne(query, modification, bldr.opts);
                            return builder;
                        }
                    }).modification(modification);
                }

            });
        }
    }

//    QueryBuilder>>>
    static class ReplaceFactory implements Factory, T>> {

        private final CollectionPromises promises;

        public ReplaceFactory(CollectionPromises promises) {
            this.promises = promises;
        }

        @Override
        public ReplaceBuilder, T> create(final Document document) {
            return new ReplaceBuilderImpl<>(new ReplaceBuilderImpl.Factory, T>() {

                @Override
                public AsyncPromise replace(ReplaceBuilderImpl, T> builder, T replacement) {
                    return AsyncPromise.create(new Logic() {

                        @Override
                        public void run(Void data, Trigger next, PromiseContext context) throws Exception {
                            next.trigger(document, null);
                        }
                    }).then(promises.replaceOne(replacement, builder.opts));
                }
            });
        }

    }

    static class FindAndModifyOneFactory implements Factory>> {

        private final CollectionPromises promises;

        public FindAndModifyOneFactory(CollectionPromises promises) {
            this.promises = promises;
        }

        @Override
        public ModificationBuilder> create(final Document query) {
            return new ModificationBuilderImpl<>(new ModificationBuilderImpl.Factory>() {

                @Override
                public FindOneAndUpdateBuilder build(final Document modification) {
                    FindOneAndUpdateBuilderImpl.Factory factory = new FindOneAndUpdateBuilderImpl.Factory() {

                        @Override
                        public AsyncPromise build(final FindOneAndUpdateBuilderImpl builder) {
                            return AsyncPromise.create(new Logic() {

                                @Override
                                public void run(Void data, Trigger next, PromiseContext context) throws Exception {
                                    next.trigger(query, null);
                                }
                            }).then(promises.findOneAndUpdate(modification, builder.opts));
                        }
                    };
                    return new FindOneAndUpdateBuilderImpl(factory);
                }
            });
        }
    }

    static class FindFactory implements Factory> {

        private final CollectionPromises promises;

        public FindFactory(CollectionPromises promises) {
            this.promises = promises;
        }

        @Override
        public FindBuilder create(Document document) {
            return FindBuilderImpl.create(promises, document);
        }
    }

    static class CountFactory implements Factory> {

        private final CollectionPromises promises;

        public CountFactory(CollectionPromises promises) {
            this.promises = promises;
        }

        @Override
        public CountBuilder create(Document document) {
            return CountBuilderImpl.create(promises, document);
        }
    }

    @Override
    public QueryBuilder equal(String key, Object value) {
        equal.put(key, value);
        return this;
    }

    @Override
    public QueryBuilder in(String key, Object... values) {
        if (values.length == 1 && values[0] instanceof Collection) {
            in.put(key, ((Collection) values[0]).toArray());
        } else {
            in.put(key, values);
        }
        return this;
    }

    @Override
    public QueryBuilder greaterThan(String key, Number value) {
        greaterThan.put(key, value);
        return this;
    }

    @Override
    public QueryBuilder lessThan(String key, Number value) {
        lessThan.put(key, value);
        return this;
    }

    @Override
    public QueryBuilder greaterThanOrEqual(String key, Number value) {
        greaterThanOrEqual.put(key, value);
        return this;
    }

    @Override
    public QueryBuilder lessThanOrEqual(String key, Number value) {
        lessThanOrEqual.put(key, value);
        return this;
    }

    @Override
    public QueryBuilder id(Object id) {
        return equal("_id", id);
    }

    public QueryBuilder> exactSubdocument(final String elem) {
        Factory> f = new Factory>() {

            @Override
            public QueryBuilder create(Document document) {
                equal.put(elem, document);
                return QueryBuilderImpl.this;
            }

        };
        return new QueryBuilderImpl<>(f);
    }

    public QueryBuilder> embedded(final String elem) {
        Factory> f = new Factory>() {

            @Override
            public QueryBuilder create(Document document) {
                for (Map.Entry e : document.entrySet()) {
                    equal.put(elem + "." + e.getKey(), e.getValue());
                }
                return QueryBuilderImpl.this;
            }
        };
        return new QueryBuilderImpl<>(f);
    }

    public QueryBuilder> elemMatch(final String elem) {
        return new QueryBuilderImpl<>(new Factory>() {

            @Override
            public QueryBuilder create(Document document) {
                QueryBuilderImpl.this.elemMatch.put(elem, new Document("$elemMatch", document));
                return QueryBuilderImpl.this;
            }
        });
    }

    interface Factory {

        R create(Document document);
    }

    public R build() {
        return factory.create(toDocument());
    }

    Document toDocument() {
        Document result = new Document(equal);
        if (!in.isEmpty()) {
            for (Map.Entry e : in.entrySet()) {
                Document sub = new Document();
                sub.append("$in", Arrays.asList(e.getValue()));
                result.append(e.getKey(), sub);
            }
        }
        Set keys = new HashSet<>(greaterThan.keySet());
        keys.addAll(lessThan.keySet());
        keys.addAll(lessThanOrEqual.keySet());
        keys.addAll(greaterThanOrEqual.keySet());
        for (String k : keys) {
            Document d = new Document();
            Number gt = greaterThan.get(k);
            Number lt = lessThan.get(k);
            Number gte = greaterThanOrEqual.get(k);
            Number lte = lessThanOrEqual.get(k);
            if (gt != null) {
                d.append("$gt", gt);
            }
            if (lt != null) {
                d.append("$lt", lt);
            }
            if (gte != null) {
                d.append("$gte", gte);
            }
            if (lte != null) {
                d.append("$lte", lte);
            }
            result.append(k, d);
        }
        for (Map.Entry e : elemMatch.entrySet()) {
            result.put(e.getKey(), e.getValue());
        }
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy