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.mysema.query.collections.DefaultEvaluatorFactory Maven / Gradle / Ivy
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.query.collections;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import net.jcip.annotations.Immutable;
import org.apache.commons.lang.ClassUtils;
import com.mysema.codegen.Evaluator;
import com.mysema.codegen.EvaluatorFactory;
import com.mysema.codegen.model.ClassType;
import com.mysema.codegen.model.SimpleType;
import com.mysema.codegen.model.Type;
import com.mysema.codegen.model.TypeCategory;
import com.mysema.codegen.model.Types;
import com.mysema.query.JoinExpression;
import com.mysema.query.JoinType;
import com.mysema.query.QueryMetadata;
import com.mysema.query.support.CollectionAnyVisitor;
import com.mysema.query.support.Context;
import com.mysema.query.types.Expression;
import com.mysema.query.types.FactoryExpression;
import com.mysema.query.types.Operation;
import com.mysema.query.types.ParamExpression;
import com.mysema.query.types.ParamNotSetException;
import com.mysema.query.types.Predicate;
/**
* DefaultEvaluatorFactory extends the EvaluatorFactory class to provide Java source
* templates for evaluation of ColQuery queries
*
* @author tiwe
*
*/
@Immutable
public class DefaultEvaluatorFactory {
private final EvaluatorFactory factory;
private final ColQueryTemplates templates;
public DefaultEvaluatorFactory(ColQueryTemplates templates){
// TODO : which ClassLoader to pick ?!?
this(templates,
(URLClassLoader)DefaultEvaluatorFactory.class.getClassLoader(),
ToolProvider.getSystemJavaCompiler());
}
public DefaultEvaluatorFactory(ColQueryTemplates templates,
URLClassLoader classLoader, JavaCompiler compiler){
this.templates = templates;
this.factory = new EvaluatorFactory(classLoader, compiler);
}
/**
* Create an Evaluator for the given query sources and projection
*
* @param
* @param sources
* @param projection
* @return
*/
public Evaluator create(QueryMetadata metadata, List extends Expression>> sources, Expression projection) {
ColQuerySerializer serializer = new ColQuerySerializer(templates);
serializer.handle(projection);
Map constantToLabel = serializer.getConstantToLabel();
Map constants = getConstants(metadata, constantToLabel);
Class>[] types = new Class>[sources.size()];
String[] names = new String[sources.size()];
for (int i = 0; i < sources.size(); i++) {
types[i] = sources.get(i).getType();
names[i] = sources.get(i).toString();
}
// normalize types
for (int i = 0; i < types.length; i++){
if (ClassUtils.wrapperToPrimitive(types[i]) != null){
types[i] = ClassUtils.wrapperToPrimitive(types[i]);
}
}
String javaSource = serializer.toString();
if (projection instanceof FactoryExpression>){
javaSource = "("+com.mysema.codegen.support.ClassUtils.getName(projection.getType())+")(" + javaSource+")";
}
return factory.createEvaluator("return " + javaSource +";", projection.getType(), names, types, constants);
}
/**
* Create an Evaluator for the given source and filter
*
* @param
* @param source
* @param filter
* @return
*/
public Evaluator> createEvaluator(QueryMetadata metadata, Expression extends T> source, Predicate filter){
String typeName = com.mysema.codegen.support.ClassUtils.getName(source.getType());
ColQuerySerializer ser = new ColQuerySerializer(templates);
ser.append("java.util.List<"+typeName+"> rv = new java.util.ArrayList<"+typeName+">();\n");
ser.append("for (" + typeName + " "+ source + " : " + source + "_){\n");
ser.append(" if (").handle(filter).append("){\n");
ser.append(" rv.add("+source+");\n");
ser.append(" }\n");
ser.append("}\n");
ser.append("return rv;");
Map constantToLabel = ser.getConstantToLabel();
Map constants = getConstants(metadata, constantToLabel);
Type sourceType = new ClassType(TypeCategory.SIMPLE, source.getType());
ClassType sourceListType = new ClassType(TypeCategory.SIMPLE, Iterable.class, sourceType);
return factory.createEvaluator(
ser.toString(),
sourceListType,
new String[]{source+"_"},
new Type[]{sourceListType},
new Class[]{Iterable.class},
constants);
}
/**
* Create an Evaluator for the given sources and the given optional filter
*
* @param joins
* @param filter
* @return
*/
@SuppressWarnings("unchecked")
public Evaluator> createEvaluator(QueryMetadata metadata, List joins, @Nullable Predicate filter){
List sourceNames = new ArrayList();
List sourceTypes = new ArrayList();
List sourceClasses = new ArrayList();
StringBuilder vars = new StringBuilder();
ColQuerySerializer ser = new ColQuerySerializer(templates);
ser.append("java.util.List rv = new java.util.ArrayList();\n");
List anyJoinMatchers = new ArrayList();
// creating context
for (JoinExpression join : joins){
Expression> target = join.getTarget();
String typeName = com.mysema.codegen.support.ClassUtils.getName(target.getType());
if (vars.length() > 0){
vars.append(",");
}
if (join.getType() == JoinType.DEFAULT){
ser.append("for (" + typeName + " "+ target + " : " + target + "_){\n");
vars.append(target);
sourceNames.add(target+"_");
sourceTypes.add(new SimpleType(Types.ITERABLE, new ClassType(TypeCategory.SIMPLE,target.getType())));
sourceClasses.add(Iterable.class);
}else if (join.getType() == JoinType.INNERJOIN){
Operation alias = (Operation)join.getTarget();
boolean colAnyJoin = join.getCondition() != null && join.getCondition().toString().equals("any");
if (colAnyJoin){
String matcher = alias.getArg(1).toString() + "_matched";
ser.append("boolean " + matcher + " = false;\n");
anyJoinMatchers.add(matcher);
}
ser.append("for ( " + typeName + " " + alias.getArg(1) + " : ");
if (colAnyJoin){
Context context = new Context();
Expression> replacement = (Expression>) alias.getArg(0).accept(CollectionAnyVisitor.DEFAULT, context);
ser.handle(replacement);
}else{
ser.handle(alias.getArg(0));
}
if (alias.getArg(0).getType().equals(Map.class)){
ser.append(".values()");
}
ser.append("){\n");
vars.append(alias.getArg(1));
}else{
throw new IllegalArgumentException("Illegal join expression " + join);
}
}
// filter
if (filter != null){
ser.append("if (");
for (String matcher : anyJoinMatchers){
ser.append("!" + matcher + " && ");
}
ser.handle(filter).append("){\n");
for (String matcher : anyJoinMatchers){
ser.append(" "+ matcher + " = true;\n");
}
ser.append(" rv.add(new Object[]{"+vars+"});\n");
ser.append("}\n");
}else{
ser.append("rv.add(new Object[]{"+vars+"});\n");
}
// closing context
for (int i = 0; i < joins.size(); i++){
ser.append("}\n");
}
ser.append("return rv;");
Map constantToLabel = ser.getConstantToLabel();
Map constants = getConstants(metadata, constantToLabel);
ClassType projectionType = new ClassType(TypeCategory.LIST, List.class, Types.OBJECTS);
return factory.createEvaluator(
ser.toString(),
projectionType,
sourceNames.toArray(new String[sourceNames.size()]),
sourceTypes.toArray(new Type[sourceTypes.size()]),
sourceClasses.toArray(new Class[sourceClasses.size()]),
constants);
}
private Map getConstants(QueryMetadata metadata, Map constantToLabel) {
Map constants = new HashMap();
for (Map.Entry entry : constantToLabel.entrySet()){
if (entry.getKey() instanceof ParamExpression>){
Object value = metadata.getParams().get(entry.getKey());
if (value == null){
throw new ParamNotSetException((ParamExpression>) entry.getKey());
}
constants.put(entry.getValue(), value);
}else{
constants.put(entry.getValue(), entry.getKey());
}
}
return constants;
}
}