/** * Create an Evaluator for the given sources and the given optional filter * * @param metadata query metadata * @param joins joins * @param filter where condition * @return evaluator */ @SuppressWarnings("unchecked") public Evaluator<List<Object[]>> createEvaluator( QueryMetadata metadata, List<JoinExpression> joins, @Nullable Predicate filter) { List<String> sourceNames = new ArrayList<String>(); List<Type> sourceTypes = new ArrayList<Type>(); List<Class<?>> sourceClasses = new ArrayList<Class<?>>(); StringBuilder vars = new StringBuilder(); CollQuerySerializer ser = new CollQuerySerializer(templates); ser.append("java.util.List<Object[]> rv = new java.util.ArrayList<Object[]>();\n"); List<String> anyJoinMatchers = new ArrayList<String>(); // 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(","); } switch (join.getType()) { case 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); break; case INNERJOIN: case LEFTJOIN: Operation<?> alias = (Operation<?>) join.getTarget(); boolean colAnyJoin = join.getCondition() != null && join.getCondition().toString().equals("any"); boolean leftJoin = join.getType() == JoinType.LEFTJOIN; String matcher = null; if (colAnyJoin) { matcher = alias.getArg(1).toString() + "_matched"; ser.append("boolean " + matcher + " = false;\n"); anyJoinMatchers.add(matcher); } ser.append("for (" + typeName + " " + alias.getArg(1) + " : "); if (leftJoin) { ser.append(CollQueryFunctions.class.getName() + ".leftJoin("); } if (colAnyJoin) { Context context = new Context(); Expression<?> replacement = alias.getArg(0).accept(collectionAnyVisitor, context); ser.handle(replacement); } else { ser.handle(alias.getArg(0)); } if (alias.getArg(0).getType().equals(Map.class)) { ser.append(".values()"); } if (leftJoin) { ser.append(")"); } ser.append(") {\n"); if (matcher != null) { ser.append("if (!" + matcher + ") {\n"); } vars.append(alias.getArg(1)); break; default: throw new IllegalArgumentException("Illegal join expression " + join); } } // filter if (filter != null) { ser.append("try {\n"); ser.append("if ("); 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"); ser.append("} catch (NullPointerException npe) { }\n"); } else { ser.append("rv.add(new Object[]{" + vars + "});\n"); } // closing context int amount = joins.size() + anyJoinMatchers.size(); for (int i = 0; i < amount; i++) { ser.append("}\n"); } ser.append("return rv;"); Map<Object, String> constantToLabel = ser.getConstantToLabel(); Map<String, Object> 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); }
/** * Create an Evaluator for the given query sources and projection * * @param <T> * @param metadata query metadata * @param sources sources of the query * @param projection projection of the query * @return evaluator */ public <T> Evaluator<T> create( QueryMetadata metadata, List<? extends Expression<?>> sources, Expression<T> projection) { final CollQuerySerializer serializer = new CollQuerySerializer(templates); serializer.append("return "); if (projection instanceof FactoryExpression<?>) { serializer.append("("); serializer.append(ClassUtils.getName(projection.getType())); serializer.append(")("); serializer.handle(projection); serializer.append(")"); } else { serializer.handle(projection); } serializer.append(";"); Map<Object, String> constantToLabel = serializer.getConstantToLabel(); Map<String, Object> 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 (Primitives.isWrapperType(types[i])) { types[i] = Primitives.unwrap(types[i]); } } return factory.createEvaluator( serializer.toString(), projection.getType(), names, types, constants); }
/** * Create an Evaluator for the given source and filter * * @param <T> * @param source source of the query * @param filter filter of the query * @return evaluator */ @SuppressWarnings("unchecked") public <T> Evaluator<List<T>> createEvaluator( QueryMetadata metadata, Expression<? extends T> source, Predicate filter) { String typeName = ClassUtils.getName(source.getType()); CollQuerySerializer ser = new CollQuerySerializer(templates); ser.append( "java.util.List<" + typeName + "> rv = new java.util.ArrayList<" + typeName + ">();\n"); ser.append("for (" + typeName + " " + source + " : " + source + "_) {\n"); ser.append(" try {\n"); ser.append(" if (").handle(filter).append(") {\n"); ser.append(" rv.add(" + source + ");\n"); ser.append(" }\n"); ser.append(" } catch (NullPointerException npe) { }\n"); ser.append("}\n"); ser.append("return rv;"); Map<Object, String> constantToLabel = ser.getConstantToLabel(); Map<String, Object> 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); }