org.eclipselabs.mongoemf.query.simple.SimpleQueryEngine.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipselabs.mongoemf.query.simple.SimpleQueryEngine.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Bryan Hunt and Ed Merks.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Bryan Hunt and Ed Merks - initial API and implementation
 *******************************************************************************/

package org.eclipselabs.mongoemf.query.simple;

import java.util.ArrayList;
import java.util.List;

import org.bson.types.ObjectId;
import org.eclipse.emf.common.util.URI;
import org.eclipselabs.emodeling.query.BinaryOperation;
import org.eclipselabs.emodeling.query.Expression;
import org.eclipselabs.emodeling.query.Literal;
import org.eclipselabs.emodeling.query.util.ExpressionBuilder;
import org.eclipselabs.emodeling.query.util.QuerySwitch;
import org.eclipselabs.mongoemf.Keywords;
import org.eclipselabs.mongoemf.QueryEngine;
import org.eclipselabs.mongoemf.model.ModelFactory;
import org.eclipselabs.mongoemf.model.MongoQuery;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.QueryOperators;

/**
 * @author merks
 * 
 */
public class SimpleQueryEngine implements QueryEngine {

    @Override
    public MongoQuery buildDBObjectQuery(URI uri) {
        MongoQuery mongoQuery = ModelFactory.eINSTANCE.createMongoQuery();
        mongoQuery.setFilter(buildDBObjectQuery(new ExpressionBuilder(URI.decode(uri.query())).parseExpression()));
        return mongoQuery;
    }

    private DBObject buildDBObjectQuery(Expression expression) {
        final DBObject dbObject = new BasicDBObject();

        if (expression != null) {
            new QuerySwitch<Object>() {
                Object getValue(Literal literal) {
                    return literal.getValue() == null ? literal.getLiteralValue() : literal.getValue();
                }

                @Override
                public Object caseBinaryOperation(BinaryOperation binaryOperation) {
                    Expression leftOperand = binaryOperation.getLeftOperand();
                    String operator = binaryOperation.getOperator();

                    if ("==".equals(operator)) {
                        Expression rightOperand = binaryOperation.getRightOperand();
                        String property = ExpressionBuilder.toString(leftOperand);

                        if (Keywords.ID_KEY.equals(property)) {
                            dbObject.put(property, new ObjectId(((Literal) rightOperand).getLiteralValue()));
                        } else if (rightOperand instanceof Literal) {
                            dbObject.put(property, getValue((Literal) rightOperand));
                        } else if ("null".equals(ExpressionBuilder.toString(rightOperand))) {
                            DBObject notExists = new BasicDBObject();
                            notExists.put("$exists", Boolean.FALSE);
                            dbObject.put(property, notExists);
                        } else {
                            // TODO: What to do?
                        }
                    } else if ("!=".equals(operator)) {
                        Expression rightOperand = binaryOperation.getRightOperand();
                        String property = ExpressionBuilder.toString(leftOperand);
                        if (rightOperand instanceof Literal) {
                            DBObject notEqual = new BasicDBObject();
                            notEqual.put("$ne", getValue((Literal) rightOperand));
                            dbObject.put(property, notEqual);
                        } else if ("null".equals(ExpressionBuilder.toString(rightOperand))) {
                            DBObject exists = new BasicDBObject();
                            exists.put("$exists", Boolean.TRUE);
                            dbObject.put(property, exists);
                        } else {
                            // TODO: What to do?
                        }
                    } else if ("<".equals(operator) || "<=".equals(operator) || ">".equals(operator)
                            || ">=".equals(operator)) {
                        Expression rightOperand = binaryOperation.getRightOperand();
                        String property = ExpressionBuilder.toString(leftOperand);
                        if (rightOperand instanceof Literal) {
                            DBObject compare = new BasicDBObject();
                            compare.put(
                                    "<".equals(operator) ? QueryOperators.LT
                                            : "<=".equals(operator) ? QueryOperators.LTE
                                                    : ">".equals(operator) ? QueryOperators.GT : QueryOperators.GTE,
                                    getValue((Literal) rightOperand));
                            dbObject.put(property, compare);
                        } else {
                            // TODO: What to do?
                        }
                    } else if ("||".equals(operator)) {
                        DBObject leftObject = buildDBObjectQuery(leftOperand);
                        DBObject rightObject = buildDBObjectQuery(binaryOperation.getRightOperand());
                        @SuppressWarnings("unchecked")
                        List<Object> or = (List<Object>) leftObject.get("$or");
                        if (or != null) {
                            or.add(rightObject);
                            dbObject.putAll(leftObject);
                        } else {
                            or = new ArrayList<Object>();
                            or.add(leftObject);
                            or.add(rightObject);
                            dbObject.put("$or", or);
                        }
                    } else if ("&&".equals(operator)) {
                        dbObject.putAll(buildDBObjectQuery(leftOperand));
                        DBObject rightObject = buildDBObjectQuery(binaryOperation.getRightOperand());
                        for (String field : rightObject.keySet()) {
                            Object rightValue = rightObject.get(field);
                            Object leftValue = dbObject.get(field);
                            if (leftValue instanceof DBObject) {
                                DBObject leftDBObject = (DBObject) leftValue;
                                if (rightValue instanceof DBObject) {
                                    DBObject rightDBObject = (DBObject) rightValue;
                                    if (leftDBObject.containsField("$nin") && rightDBObject.containsField("$ne")) {
                                        @SuppressWarnings("unchecked")
                                        List<Object> values = (List<Object>) leftDBObject.get("$nin");
                                        values.add(rightDBObject.get("$ne"));
                                    } else if (leftDBObject.containsField("$ne")
                                            && rightDBObject.containsField("$ne")) {
                                        DBObject nin = new BasicDBObject();
                                        List<Object> values = new ArrayList<Object>();
                                        values.add(leftDBObject.get("$ne"));
                                        values.add(rightDBObject.get("$ne"));
                                        nin.put("$nin", values);
                                        dbObject.put(field, nin);
                                    } else {
                                        leftDBObject.putAll(rightDBObject);
                                    }
                                } else {
                                    Object all = leftDBObject.get("$all");
                                    if (all instanceof List<?>) {
                                        @SuppressWarnings("unchecked")
                                        List<Object> allList = (List<Object>) all;
                                        allList.add(rightValue);
                                    } else {
                                        // What to do?
                                    }
                                }
                            } else if (leftValue instanceof List<?>) {
                                @SuppressWarnings("unchecked")
                                List<Object> leftListValue = (List<Object>) leftValue;
                                if (rightValue instanceof List<?>) {
                                    leftListValue.addAll((List<?>) rightValue);
                                } else {
                                    leftListValue.add(rightValue);
                                }
                            } else if (leftValue != null) {
                                if (rightValue instanceof List<?>) {
                                    @SuppressWarnings("unchecked")
                                    List<Object> rightListValue = (List<Object>) rightValue;
                                    rightListValue.add(0, leftValue);
                                    dbObject.put(field, rightListValue);
                                } else {
                                    List<Object> listValue = new ArrayList<Object>();
                                    listValue.add(leftValue);
                                    listValue.add(rightValue);
                                    DBObject in = new BasicDBObject("$all", listValue);
                                    dbObject.put(field, in);
                                }
                            } else {
                                dbObject.put(field, rightValue);
                            }
                        }
                    }

                    return null;
                }
            }.doSwitch(expression);
        }

        return dbObject;
    }
}