Result of calling TextFragment.balanceMarkers() second time differs from that of the first call

Issue #792 resolved
Kuro Kurosaka created an issue

TextFragment.balanceMarkers() should be idempotent, meaning after calling it on a TextFragment object, calling it second time or more should not change the object.

But the following test case shows it is not idempotent.

    @Test
    public void testBalanceMarkerIdempotent() {
        // "<t>abc<u>xxx</t>def</u>"
        // <u> and </u> should be marked isolated so XLIFF is well-formed.
        TextFragment tf = new TextFragment();
        Code code = new Code(TagType.OPENING, "ttag", "<t>");
        code.setId(1);
        tf.append(code);
        tf.append("abc");
        code = new Code(TagType.OPENING, "utag", "<u>");
        code.setId(2);
        tf.append(code);
        tf.append("xxx");
        code = new Code(TagType.CLOSING, "ttag", "</t>");
        tf.append(code);
        tf.append("def");
        code = new Code(TagType.CLOSING, "utag", "</u>");
        tf.append(code);

        tf.balanceMarkers(); // First call. Note the following tf.getCodes() would make this call internally if this line weren't here.

        assertThat(tf.getCodes().size(), equalTo(4));
        assertThat(tf.getCodes().get(0).getId(), equalTo(1));
        assertThat(tf.getCodes().get(1).getId(), equalTo(2));
        assertThat(tf.getCodes().get(2).getId(), equalTo(1));
        assertThat(tf.getCodes().get(3).getId(), equalTo(2));
        String t1 = tf.getCodedText();

        tf.balanceMarkers(); // Second call.

        assertThat(tf.getCodes().size(), equalTo(4));
        assertThat(tf.getCodes().get(0).getId(), equalTo(1));
        assertThat(tf.getCodes().get(1).getId(), equalTo(2));
        assertThat(tf.getCodes().get(2).getId(), equalTo(1));
        assertThat(tf.getCodes().get(3).getId(), equalTo(2));
        String t2 = tf.getCodedText();
        assertThat(t2, equalTo(t1));
    }

This issue has been a part of the issue #791. It has been converted to a separate issue for clarity.

NOTE: This may be occurring only in cases like this where the code pairs overlap each othe. The balanceMarkers() logic may be naturally idempotent otherwise.

Comments (4)

  1. Kuro Kurosaka reporter

    This is a quick fix to skip everything if isBalanced is true at the entry of balanceMarkers(). If there is a need to force running the logic again for some reason, invalidate() must be called on the TextFragment before calling balanceMarkers().

  2. Log in to comment