Added couple of new operators

This commit is contained in:
Lassi Immonen 2010-09-14 13:59:36 +00:00
parent de4615bbd3
commit 3789fcb1e3
2 changed files with 162 additions and 99 deletions

View File

@ -1,5 +1,12 @@
package com.mysema.query.mongodb;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.bson.BSONObject;
import com.mongodb.BasicDBObject;
import com.mysema.query.types.Constant;
import com.mysema.query.types.Custom;
@ -15,114 +22,123 @@ import com.mysema.query.types.Visitor;
/**
* Serializes the given QueryDSL query to a DBObject querty format MongoDB understands.
*
* @author laimw
*
*
*/
public class MongodbSerializer implements Visitor<Object, Void> {
// public MongodbSerializer() {
// //BasicDBObject o = new BasicDBObject();
// //o.append("firstName", "Juuso");
//
// //o.append("firstName", new BasicDBObject("$ne", "Juuso"));
// //o.append("age", 3);
// }
// public MongodbSerializer() {
// //BasicDBObject o = new BasicDBObject();
// //o.append("firstName", "Juuso");
//
// //o.append("firstName", new BasicDBObject("$ne", "Juuso"));
// //o.append("age", 3);
// }
public Object handle(Expr<?> where) {
return where.accept(this, null);
}
public Object handle(Expr<?> where) {
return where.accept(this, null);
}
@Override
public Object visit(Constant<?> expr, Void context) {
return expr.getConstant();
}
@Override
public Object visit(Constant<?> expr, Void context) {
return expr.getConstant();
}
@Override
public Object visit(Custom<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object visit(Custom<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object visit(FactoryExpression<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
}
private String leftAsString(Operation<?> expr) {
return (String)expr.getArg(0).accept(this, null);
}
private Object rightAsObj(Operation<?> expr) {
return expr.getArg(1).accept(this, null);
}
@Override
public Object visit(FactoryExpression<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object visit(Operation<?> expr, Void context) {
Operator<?> op = expr.getOperator();
// if (op == Ops.OR) {
// return toTwoHandSidedQuery(operation, Occur.SHOULD, metadata);
// } else if (op == Ops.AND) {
// return toTwoHandSidedQuery(operation, Occur.MUST, metadata);
// } else if (op == Ops.NOT) {
// BooleanQuery bq = new BooleanQuery();
// bq.add(new BooleanClause(toQuery(operation.getArg(0), metadata), Occur.MUST_NOT));
// return bq;
// } else if (op == Ops.LIKE) {
// return like(operation, metadata);
if (op == Ops.EQ_OBJECT || op == Ops.EQ_PRIMITIVE || op == Ops.EQ_IGNORE_CASE) {
return new BasicDBObject(leftAsString(expr), rightAsObj(expr));
}
if (op == Ops.AND) {
BasicDBObject left = (BasicDBObject) handle(expr.getArg(0));
BasicDBObject right = (BasicDBObject) handle(expr.getArg(1));
left.putAll(right.toMap());
return left;
}
if (op == Ops.NE_OBJECT || op == Ops.NE_PRIMITIVE) {
return new BasicDBObject(leftAsString(expr), new BasicDBObject("$ne", rightAsObj(expr)));
}
// } else if (op == Ops.STARTS_WITH || op == Ops.STARTS_WITH_IC) {
// return startsWith(metadata, operation);
// } else if (op == Ops.ENDS_WITH || op == Ops.ENDS_WITH_IC) {
// return endsWith(operation, metadata);
// } else if (op == Ops.STRING_CONTAINS || op == Ops.STRING_CONTAINS_IC) {
// return stringContains(operation, metadata);
// } else if (op == Ops.BETWEEN) {
// return between(operation, metadata);
// } else if (op == Ops.IN) {
// return in(operation, metadata);
// } else if (op == Ops.LT || op == Ops.BEFORE) {
// return lt(operation, metadata);
// } else if (op == Ops.GT || op == Ops.AFTER) {
// return gt(operation, metadata);
// } else if (op == Ops.LOE || op == Ops.BOE) {
// return le(operation, metadata);
// } else if (op == Ops.GOE || op == Ops.AOE) {
// return ge(operation, metadata);
// } else if (op == PathType.DELEGATE) {
// return toQuery(operation.getArg(0), metadata);
// }
throw new UnsupportedOperationException("Illegal operation " + expr);
}
private String asString(Operation<?> expr, int index) {
return (String) expr.getArg(index).accept(this, null);
}
@Override
public Object visit(Path<?> expr, Void context) {
return expr.getMetadata().getExpression().toString();
}
private Object asObj(Operation<?> expr, int index) {
return expr.getArg(index).accept(this, null);
}
@Override
public Object visit(SubQueryExpression<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
}
private BasicDBObject dbo(String key, Object value) {
return new BasicDBObject(key, value);
}
@Override
public Object visit(Param<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
@Override
public Object visit(Operation<?> expr, Void context) {
Operator<?> op = expr.getOperator();
// if (op == Ops.OR) {
// return toTwoHandSidedQuery(operation, Occur.SHOULD, metadata);
// } else if (op == Ops.NOT) {
// BooleanQuery bq = new BooleanQuery();
// bq.add(new BooleanClause(toQuery(operation.getArg(0), metadata), Occur.MUST_NOT));
// return bq;
// } else if (op == Ops.LIKE) {
// return like(operation, metadata);
if (op == Ops.EQ_OBJECT || op == Ops.EQ_PRIMITIVE /* || op == Ops.EQ_IGNORE_CASE */) {
return dbo(asString(expr, 0), asObj(expr, 1));
}
if (op == Ops.AND) {
BasicDBObject left = (BasicDBObject) handle(expr.getArg(0));
left.putAll((BSONObject) handle(expr.getArg(1)));
return left;
}
if (op == Ops.NE_OBJECT || op == Ops.NE_PRIMITIVE) {
return dbo(asString(expr, 0), dbo("$ne", asObj(expr, 1)));
}
// } else if (op == Ops.STARTS_WITH || op == Ops.STARTS_WITH_IC) {
// return startsWith(metadata, operation);
// } else if (op == Ops.ENDS_WITH || op == Ops.ENDS_WITH_IC) {
// return endsWith(operation, metadata);
// } else if (op == Ops.STRING_CONTAINS || op == Ops.STRING_CONTAINS_IC) {
// return stringContains(operation, metadata);
if (op == Ops.BETWEEN) {
BasicDBObject value = new BasicDBObject("$gt", asObj(expr, 1));
value.append("$lt", asObj(expr, 2));
return dbo(asString(expr, 0), value);
}
if (op == Ops.IN) {
Collection<?> values = (Collection<?>) ((Constant<?>) expr.getArg(1)).getConstant();
return dbo(asString(expr, 0), dbo("$in",values.toArray()));
}
if (op == Ops.LT || op == Ops.BEFORE) {
return dbo(asString(expr, 0), dbo("$lt", asObj(expr, 1)));
}
if (op == Ops.GT || op == Ops.AFTER) {
return dbo(asString(expr, 0), dbo("$gt", asObj(expr, 1)));
}
if (op == Ops.LOE || op == Ops.BOE) {
return dbo(asString(expr, 0), dbo("$lte", asObj(expr, 1)));
}
if (op == Ops.GOE || op == Ops.AOE) {
return dbo(asString(expr, 0), dbo("$gte", asObj(expr, 1)));
}
// } else if (op == PathType.DELEGATE) {
// return toQuery(operation.getArg(0), metadata);
// }
throw new UnsupportedOperationException("Illegal operation " + expr);
}
}
@Override
public Object visit(Path<?> expr, Void context) {
return expr.getMetadata().getExpression().toString();
}
@Override
public Object visit(SubQueryExpression<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object visit(Param<?> expr, Void context) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -2,11 +2,19 @@ package com.mysema.query.mongodb;
import static junit.framework.Assert.assertEquals;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.bson.BSONObject;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.BasicDBObject;
import com.mysema.query.types.Expr;
import com.mysema.query.types.path.PDate;
import com.mysema.query.types.path.PDateTime;
import com.mysema.query.types.path.PNumber;
import com.mysema.query.types.path.PString;
import com.mysema.query.types.path.PathBuilder;
@ -23,6 +31,11 @@ public class MongodbSerializerTest {
private PNumber<Byte> byteField;
private PNumber<Float> floatField;
private PDate<Date> date;
private Date dateVal = new Date();
private PDateTime<Timestamp> dateTime;
private Timestamp dateTimeVal = new Timestamp(System.currentTimeMillis());
private MongodbSerializer serializer;
@Before
@ -36,6 +49,8 @@ public class MongodbSerializerTest {
shortField = entityPath.getNumber("shortField", Short.class);
byteField = entityPath.getNumber("byteField", Byte.class);
floatField = entityPath.getNumber("floatField", Float.class);
date = entityPath.getDate("date", Date.class);
dateTime = entityPath.getDateTime("dateTime", Timestamp.class);
}
@Test
@ -47,6 +62,9 @@ public class MongodbSerializerTest {
assertQuery(shortField.eq((short)1), dbo("shortField", 1));
assertQuery(byteField.eq((byte)1), dbo("byteField", 1L));
assertQuery(floatField.eq(1.0F), dbo("floatField", 1.0F));
assertQuery(date.eq(dateVal), dbo("date", dateVal));
assertQuery(dateTime.eq(dateTimeVal), dbo("dateTime", dateTimeVal));
}
@Test
@ -67,14 +85,43 @@ public class MongodbSerializerTest {
assertQuery(title.ne("A"), dbo("title", dbo("$ne", "A")));
}
@Test
public void testLessAndGreaterAndBetween() {
assertQuery(title.lt("A"), dbo("title", dbo("$lt", "A")));
assertQuery(year.gt(1), dbo("year", dbo("$gt", 1)));
assertQuery(title.loe("A"), dbo("title", dbo("$lte", "A")));
assertQuery(year.goe(1), dbo("year", dbo("$gte", 1)));
assertQuery(
year.gt(1).and(year.lt(10)),
dbo("year", dbo("$gt", 1)).
append("year", dbo("$lt", 10))
);
assertQuery(
year.between(1, 10),
dbo("year", dbo("$gt", 1).append("$lt", 10))
);
}
@Test
public void testIn() {
assertQuery(year.in(1,2,3), dbo("year", dbo("$in", 1,2,3)));
}
private void assertQuery(Expr<?> e, BasicDBObject expected) {
BasicDBObject result = (BasicDBObject) serializer.handle(e);
assertEquals(expected, result);
assertEquals(expected.toString(), result.toString());
}
private static BasicDBObject dbo(String key, Object value) {
private static BasicDBObject dbo(String key, Object... value) {
if (value.length == 1) {
return new BasicDBObject(key, value[0]);
}
return new BasicDBObject(key, value);
}