presto-main/src/main/java/io/prestosql/operator/index/DynamicTupleFilterFactory.java/DynamicTupleFilterFactory/DynamicTupleFilterFactory
class DynamicTupleFilterFactory:    public DynamicTupleFilterFactory(
            int filterOperatorId,
            PlanNodeId planNodeId,
            int[] tupleFilterChannels,
            int[] outputFilterChannels,
            List<Type> outputTypes,
            PageFunctionCompiler pageFunctionCompiler)
    {
        requireNonNull(planNodeId, "planNodeId is null");
        requireNonNull(tupleFilterChannels, "tupleFilterChannels is null");
        checkArgument(tupleFilterChannels.length > 0, "Must have at least one tupleFilterChannel");
        requireNonNull(outputFilterChannels, "outputFilterChannels is null");
        checkArgument(outputFilterChannels.length == tupleFilterChannels.length, "outputFilterChannels must have same length as tupleFilterChannels");
        requireNonNull(outputTypes, "outputTypes is null");
        checkArgument(outputTypes.size() >= outputFilterChannels.length, "Must have at least as many output channels as those used for filtering");
        requireNonNull(pageFunctionCompiler, "pageFunctionCompiler is null");

        this.filterOperatorId = filterOperatorId;
        this.planNodeId = planNodeId;

        this.tupleFilterChannels = tupleFilterChannels.clone();
        this.outputFilterChannels = ImmutableList.copyOf(Ints.asList(outputFilterChannels));
        this.filterTypes = IntStream.of(outputFilterChannels)
                .mapToObj(outputTypes::get)
                .collect(toImmutableList());

        this.outputTypes = ImmutableList.copyOf(outputTypes);
        this.outputProjections = IntStream.range(0, outputTypes.size())
                .mapToObj(field -> pageFunctionCompiler.compileProjection(Expressions.field(field, outputTypes.get(field)), Optional.empty()))
                .collect(toImmutableList());
    }