
com.mastfrog.asyncpromises.mongo.QueryBuilderImpl Maven / Gradle / Ivy
/*
* 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