class UnionConverterRule extends RelRule<UnionConverterRule.Config> {
    /** Instance. */
    public static final RelOptRule INSTANCE = Config.DEFAULT.toRule();

    /** */
    public UnionConverterRule(Config cfg) {
        super(cfg);
    }

    /** {@inheritDoc} */
    @Override public void onMatch(RelOptRuleCall call) {<FILL_FUNCTION_BODY>}

    /**
     *
     */
    @Value.Immutable
    public interface Config extends RelRule.Config {
        /** */
        UnionConverterRule.Config DEFAULT = ImmutableUnionConverterRule.Config.of()
            .withDescription("UnionConverterRule")
            .withOperandFor(LogicalUnion.class);

        /** Defines an operand tree for the given classes. */
        default UnionConverterRule.Config withOperandFor(Class<? extends LogicalUnion> union) {
            return withOperandSupplier(
                o0 -> o0.operand(union).anyInputs()
            )
                .as(UnionConverterRule.Config.class);
        }

        /** {@inheritDoc} */
        @Override default UnionConverterRule toRule() {
            return new UnionConverterRule(this);
        }
    }
}

        final LogicalUnion union = call.rel(0);

        RelOptCluster cluster = union.getCluster();
        RelTraitSet traits = cluster.traitSetOf(IgniteConvention.INSTANCE);
        List<RelNode> inputs = Commons.transform(union.getInputs(), input -> convert(input, traits));

        RelNode res = new IgniteUnionAll(cluster, traits, inputs);

        if (!union.all) {
            final RelBuilder relBuilder = relBuilderFactory.create(union.getCluster(), null);

            relBuilder
                .push(res)
                .aggregate(relBuilder.groupKey(ImmutableBitSet.range(union.getRowType().getFieldCount())));

            res = convert(relBuilder.build(), union.getTraitSet());
        }

        call.transformTo(res);
    
<no_super_class>