Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.googlecode.mjorm.mql.InterpreterImpl Maven / Gradle / Ivy
package com.googlecode.mjorm.mql;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonErrorNode;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeAdaptor;
import org.antlr.runtime.tree.Tree;
import com.googlecode.mjorm.ObjectMapper;
import com.googlecode.mjorm.query.DaoModifier;
import com.googlecode.mjorm.query.DaoQuery;
import com.googlecode.mjorm.query.Query;
import com.googlecode.mjorm.query.QueryGroup;
import com.googlecode.mjorm.query.criteria.AbstractQueryCriterion;
import com.googlecode.mjorm.query.criteria.Criterion;
import com.googlecode.mjorm.query.criteria.DocumentCriterion;
import com.googlecode.mjorm.query.criteria.EqualsCriterion;
import com.googlecode.mjorm.query.criteria.FieldCriterion;
import com.googlecode.mjorm.query.criteria.NotCriterion;
import com.googlecode.mjorm.query.criteria.RegexCriterion;
import com.googlecode.mjorm.query.criteria.SimpleCriterion;
import com.googlecode.mjorm.query.criteria.SimpleCriterion.Operator;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.WriteResult;
public class InterpreterImpl
implements Interpreter {
private static final Map NO_PARAMS
= Collections.unmodifiableMap(new HashMap());
private static final CommonTreeAdaptor ADAPTER = new CommonTreeAdaptor() {
public Object create(Token payload) {
return new CommonTree(payload);
}
};
private static final Map comparisonOperators
= new HashMap();
static {
comparisonOperators.put(">", Operator.GT);
comparisonOperators.put(">=", Operator.GTE);
comparisonOperators.put("<", Operator.LT);
comparisonOperators.put("<=", Operator.LTE);
comparisonOperators.put("!=", Operator.NE);
comparisonOperators.put("<>", Operator.NE);
}
private DB db;
private ObjectMapper objectMapper;
private Map fieldFunctions;
private Map documentFunctions;
private Map variableFunctions;
/**
* Creates it.
* @param db
* @param objectMapper
*/
public InterpreterImpl(DB db, ObjectMapper objectMapper) {
this.db = db;
this.objectMapper = objectMapper;
this.documentFunctions = new HashMap();
this.fieldFunctions = new HashMap();
this.variableFunctions = new HashMap();
}
/**
* Registers a field function.
* @param function
*/
public void registerFieldFunction(MqlCriterionFunction function) {
fieldFunctions.put(function.getName().trim().toLowerCase(), function);
}
/**
* Registers a document function.
* @param function
*/
public void registerDocumentFunction(MqlCriterionFunction function) {
documentFunctions.put(function.getName().trim().toLowerCase(), function);
}
/**
* Registers a variable function.
* @param function
*/
public void registerVariableFunction(MqlVariableFunction function) {
variableFunctions.put(function.getName().trim().toLowerCase(), function);
}
/**
* Compiles the given code return the AST.
* @param ips
* @return
* @throws IOException
* @throws RecognitionException
*/
public CommonTree compile(InputStream ips)
throws IOException,
RecognitionException {
// create the lexer and parser
MqlLexer lexer = new MqlLexer(new ANTLRUpperCaseInputStream(ips));
CommonTokenStream tokens = new CommonTokenStream(lexer);
MqlParser parser = new MqlParser(tokens);
// set adapter
parser.setTreeAdaptor(ADAPTER);
// parse
MqlParser.start_return ast = parser.start();
// verify
CommonTree tree = CommonTree.class.cast(ast.getTree());
verifyTree(tree);
return tree;
}
private void verifyTree(CommonTree tree) {
if (CommonErrorNode.class.isInstance(tree)) {
throw new MqlException(tree);
}
for (int i=0; i interpret(Tree tree) {
return interpret(tree, NO_PARAMS);
}
/**
* {@inheritDoc}
*/
public List interpret(Tree tree, Object... parameters) {
Map params = new HashMap();
for (int i=0; i interpret(
Tree tree, Map parameters) {
assertTokenType(tree, MqlParser.COMMANDS);
// prepare an execution context
ExecutionContext ctx = new ExecutionContext();
ctx.params = parameters;
ctx.currentParameterIndex = 0;
// execute
List ret = new ArrayList();
for (int i=0; i query, ExecutionContext ctx) {
assertTokenType(tree, MqlParser.CRITERIA);
for (int i=0; i query, ExecutionContext ctx) {
DocumentCriterion criterion = null;
String fieldName = null;
switch (tree.getType()) {
case MqlParser.DOCUMENT_FUNCTION_CRITERION:
String functionName = child(tree, 0).getChild(0).getText().trim().toLowerCase();
Criterion c = createCriterion(tree, ctx);
if (!DocumentCriterion.class.isInstance(c)) {
throw new MqlException(
"Document function '"+functionName+"' returned a Criterion other than a DocumentCriterion");
}
criterion = DocumentCriterion.class.cast(c);
break;
case MqlParser.FIELD_FUNCTION_CRITERION:
fieldName = child(tree, 0).getText().trim();
criterion = new FieldCriterion(fieldName, createCriterion(tree, ctx));
break;
case MqlParser.COMPARE_CRITERION:
fieldName = child(tree, 0).getText().trim();
criterion = new FieldCriterion(fieldName, createCriterion(tree, ctx));
break;
case MqlParser.NEGATED_CRITERION:
fieldName = child(tree, 0).getChild(0).getText().trim();
criterion = new NotCriterion(fieldName, createCriterion(child(tree, 0), ctx));
break;
default:
assertTokenType(tree);
}
query.add(criterion);
}
/**
* Creates a {@link Criterion} from the given tree.
* @param tree
* @return
*/
private Criterion createCriterion(CommonTree tree, ExecutionContext ctx) {
switch (tree.getType()) {
case MqlParser.DOCUMENT_FUNCTION_CRITERION:
return readCriterionForFunctionCall(child(tree, 0), documentFunctions, ctx);
case MqlParser.FIELD_FUNCTION_CRITERION:
return readCriterionForFunctionCall(child(tree, 1), fieldFunctions, ctx);
case MqlParser.COMPARE_CRITERION:
String op = child(tree, 1).getText();
Object value = readVariableLiteral(child(tree, 2), ctx);
if (op.equals("=")) {
return new EqualsCriterion(value);
} else if (op.equals("=~")) {
assertType(value, tree, Pattern.class);
return new RegexCriterion(Pattern.class.cast(value));
}
return new SimpleCriterion(comparisonOperators.get(op), value);
case MqlParser.NEGATED_CRITERION:
Criterion c = createCriterion(child(tree, 0), ctx);
if (!FieldCriterion.class.isInstance(c)) {
throw new MqlException(
"NOT requires FieldCriteiron");
}
return new NotCriterion(FieldCriterion.class.cast(c));
default:
assertTokenType(tree);
return null;
}
}
/**
* Creates a {@link Criterion} for the given function call.
* @param tree
* @param functionTable
* @return
*/
private Criterion readCriterionForFunctionCall(
CommonTree tree, Map functionTable, ExecutionContext ctx) {
assertTokenType(tree, MqlParser.FUNCTION_CALL);
// get the function name
String functionName = child(tree, 0).getText().trim().toLowerCase();
Criterion ret = null;
// function not found
if (!functionTable.containsKey(functionName)) {
throw new MqlException(
"Unknown function: "+functionName);
// no arguments
} else if (tree.getChildCount()==1) {
ret = functionTable.get(functionName).createForNoArguments();
// criteria arguments
} else if (child(tree, 1).getType()==MqlParser.CRITERIA) {
Query query = new Query();
readCriteria(child(tree, 1), query, ctx);
ret = functionTable.get(functionName).createForQuery(query);
// criteria arguments
} else if (child(tree, 1).getType()==MqlParser.CRITERIA_GROUP_LIST) {
QueryGroup queryGroup = new QueryGroup();
readCriteriaGroupList(child(tree, 1), queryGroup, ctx);
ret = functionTable.get(functionName).createForQueryGroup(queryGroup);
// variable list arguments
} else if (child(tree, 1).getType()==MqlParser.VARIABLE_LIST) {
Object[] arguments = readVariableList(child(tree, 1), ctx);
ret = functionTable.get(functionName).createForArguments(arguments);
}
// return it
return ret;
}
private QueryGroup readCriteriaGroupList(CommonTree tree, QueryGroup queryGroup, ExecutionContext ctx) {
assertTokenType(tree, MqlParser.CRITERIA_GROUP_LIST);
if (queryGroup==null) {
queryGroup = new QueryGroup();
}
for (int i=0; i1
? readVariableList(child(tree, 1), ctx) : new Object[0];
return variableFunctions.get(functionName).invoke(args);
case MqlParser.PARAMETER:
String name = child(tree, 0).getText();
return ctx.getParameter(name, tree);
case MqlParser.REGEX:
return Pattern.compile(text.substring(1, text.length()-1));
case MqlParser.INTEGER:
return new Integer(text);
case MqlParser.DECIMAL:
return new Double(text);
case MqlParser.DOUBLE_QUOTED_STRING:
return evaluateString(text);
case MqlParser.SINGLE_QUOTED_STRING:
return evaluateString(text);
case MqlParser.TRUE:
return Boolean.TRUE;
case MqlParser.FALSE:
return Boolean.FALSE;
case MqlParser.ARRAY:
Object[] vars = new Object[child(tree, 0).getChildCount()];
for (int i=0; i... types) {
if (value==null) {
return;
}
for (Class> type : types) {
if (type.isInstance(value)) {
return;
}
}
throw new MqlException(tree, "Unexpected variable type");
}
/**
* A simple execution context.
*/
private class ExecutionContext {
private Map params = NO_PARAMS;
private int currentParameterIndex = 0;
private Object getParameter(String name, CommonTree tree) {
if (name.equals("?")) {
name = currentParameterIndex+"";
currentParameterIndex++;
}
if (!params.containsKey(name)) {
throw new MqlException(tree, "Parameter "+name+" was not found");
}
return params.get(name);
}
}
}