public static SingleInputSemanticProperties addSourceFieldOffset(
            SingleInputSemanticProperties props, int numInputFields, int offset) {

        SingleInputSemanticProperties offsetProps = new SingleInputSemanticProperties();
        if (props.getReadFields(0) != null) {
            FieldSet offsetReadFields = new FieldSet();
            for (int r : props.getReadFields(0)) {
                offsetReadFields = offsetReadFields.addField(r + offset);
            }
            offsetProps.addReadFields(offsetReadFields);
        }
        for (int s = 0; s < numInputFields; s++) {
            FieldSet targetFields = props.getForwardingTargetFields(0, s);
            for (int t : targetFields) {
                offsetProps.addForwardedField(s + offset, t);
            }
        }
        return offsetProps;
    }
@Test
    void testAddSourceFieldOffset() {

        SingleInputSemanticProperties semProps = new SingleInputSemanticProperties();
        semProps.addForwardedField(0, 1);
        semProps.addForwardedField(0, 4);
        semProps.addForwardedField(2, 0);
        semProps.addForwardedField(4, 3);
        semProps.addReadFields(new FieldSet(0, 3));

        SemanticProperties offsetProps = SemanticPropUtil.addSourceFieldOffset(semProps, 5, 0);

        assertThat(offsetProps.getForwardingTargetFields(0, 0)).containsExactly(4, 1);
        assertThat(offsetProps.getForwardingTargetFields(0, 1)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 2)).containsExactly(0);
        assertThat(offsetProps.getForwardingTargetFields(0, 3)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 4)).containsExactly(3);

        assertThat(offsetProps.getReadFields(0)).containsExactly(0, 3);

        offsetProps = SemanticPropUtil.addSourceFieldOffset(semProps, 5, 3);

        assertThat(offsetProps.getForwardingTargetFields(0, 0)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 1)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 2)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 3)).containsExactly(4, 1);
        assertThat(offsetProps.getForwardingTargetFields(0, 4)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 5)).containsExactly(0);
        assertThat(offsetProps.getForwardingTargetFields(0, 6)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 7)).containsExactly(3);

        assertThat(offsetProps.getReadFields(0)).containsExactly(6, 3);

        semProps = new SingleInputSemanticProperties();
        SemanticPropUtil.addSourceFieldOffset(semProps, 1, 0);

        semProps = new SingleInputSemanticProperties();
        semProps.addForwardedField(0, 0);
        semProps.addForwardedField(1, 2);
        semProps.addForwardedField(2, 4);

        offsetProps = SemanticPropUtil.addSourceFieldOffset(semProps, 3, 2);

        assertThat(offsetProps.getForwardingTargetFields(0, 0)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 1)).isEmpty();
        assertThat(offsetProps.getForwardingTargetFields(0, 2)).containsExactly(0);
        assertThat(offsetProps.getForwardingTargetFields(0, 3)).containsExactly(2);
        assertThat(offsetProps.getForwardingTargetFields(0, 4)).containsExactly(4);
    }