dk.apaq.framework.criteria.mongo.CriteriaForMongoDb Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of criteria-mongo Show documentation
Show all versions of criteria-mongo Show documentation
An implementation of the Criteria API for Mongo DB.
/*
* Copyright (C) 2011 by Apaq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package dk.apaq.framework.criteria.mongo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import dk.apaq.framework.criteria.Limit;
import dk.apaq.framework.criteria.Rule;
import dk.apaq.framework.criteria.Sorter;
import dk.apaq.framework.criteria.Sorter.SorterEntry;
import dk.apaq.framework.criteria.mongo.interpreter.CompareRuleInterpreter;
import dk.apaq.framework.criteria.mongo.interpreter.Interpreter;
import dk.apaq.framework.criteria.rules.AndRule;
import dk.apaq.framework.criteria.rules.CompareRule;
import dk.apaq.framework.criteria.rules.NotRule;
import dk.apaq.framework.criteria.rules.OrRule;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Order;
import org.springframework.data.mongodb.core.query.Query;
/**
* Translates Rule, Sorters and Limits to JPA Query.
*/
public class CriteriaForMongoDb {
private static final Map, Interpreter extends Rule>> interpreterMap = new HashMap, Interpreter extends Rule>>();
static {
interpreterMap.put(CompareRule.class, new CompareRuleInterpreter());
}
public static Query translate(Class entityClass, dk.apaq.framework.criteria.Criteria criteria) {
return translate(null, entityClass, criteria);
}
public static Query translate(String[] fields, Class entityClass, dk.apaq.framework.criteria.Criteria criteria) {
Rule rule = criteria == null ? null : criteria.getRule();
Limit limit = criteria == null ? null : criteria.getLimit();
Sorter sorter = criteria == null ? null : criteria.getSorter();
Query q = new Query();
// Handle fields
if(fields != null) {
for(String field : fields) {
q.fields().include(field);
}
}
//Handle filter
Criteria c = new Criteria();
buildCriteria(c, rule);
q.addCriteria(c);
//Handle sorting
if(sorter != null && ! sorter.getSorterEntries().isEmpty()) {
if(sorter.getSorterEntries().size()>1) {
throw new IllegalArgumentException("One a single sorter element is supported by this translator.");
}
SorterEntry entry = sorter.getSorterEntries().get(0);
q.sort().on(entry.getPropertyId(), entry.getDirection() == Sorter.Direction.Ascending ? Order.ASCENDING : Order.DESCENDING);
}
//Handle limits
if(limit != null) {
q.skip(limit.getOffset());
q.limit(limit.getCount());
}
return q;
}
private static boolean buildCriteria(Criteria clause, Rule filter) {
if (filter == null) {
return false;
}
//First try an interpreter
Interpreter interpreter = interpreterMap.get(filter.getClass());
if (interpreter != null) {
return interpreter.interpret(clause, filter);
}
//..else try our special handlers for filtercontainers.
if (filter instanceof AndRule) {
AndRule af = (AndRule) filter;
List criterias = new ArrayList();
boolean hasAddedRule = false;
for (Rule currentRule : af.getRules()) {
Criteria c = new Criteria();
boolean statementAppended = buildCriteria(c, currentRule);
if (statementAppended) {
criterias.add(c);
hasAddedRule = true;
}
}
clause.andOperator(criterias.toArray(new Criteria[0]));
return hasAddedRule;
}
if (filter instanceof OrRule) {
OrRule of = (OrRule) filter;
List criterias = new ArrayList();
boolean hasAddedRule = false;
for (Rule currentRule : of.getRules()) {
Criteria c = new Criteria();
boolean statementAppended = buildCriteria(c, currentRule);
if (statementAppended) {
criterias.add(c);
hasAddedRule = true;
}
}
clause.orOperator(criterias.toArray(new Criteria[0]));
return hasAddedRule;
}
if (filter instanceof NotRule) {
NotRule af = (NotRule) filter;
clause.not();
return buildCriteria(clause, af.getRuleElement());
}
return false;
}
}