alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (BidiConformance.java)

This example Java source code file (BidiConformance.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abc, aioobe, arabicabc, arrayindexoutofboundsexception, attributedstring, awt, bidi, exception, font, hebrewabc, iae, illegalargumentexception, nko123, pdf, string, text, unexpected, util

The BidiConformance.java Java example source code

/*
 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 6850113
 * @summary confirm the behavior of new Bidi implementation. (Backward compatibility)
 */

import java.awt.font.NumericShaper;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import java.text.Bidi;
import java.util.Arrays;

public class BidiConformance {

    /* internal flags */
    private static boolean error = false;
    private static boolean verbose = false;
    private static boolean abort = false;

    public static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            String arg = args[i];
            if (arg.equals("-verbose")) {
                verbose = true;
            } else if (arg.equals("-abort")) {
                abort = true;
            }
        }

        BidiConformance bc = new BidiConformance();
        bc.test();

        if (error) {
            throw new RuntimeException("Failed.");
        } else {
            System.out.println("Passed.");
        }
    }

    private void test() {
        testConstants();
        testConstructors();
        testMethods();

        testMethods4Constructor1();  // Bidi(AttributedCharacterIterator)
        testMethods4Constructor2();  // Bidi(String, int)
        testMethods4Constructor3();  // Bidi(char[], ...)
    }

    private void testConstants() {
        System.out.println("*** Test constants");

        checkResult("Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT",
                     -2, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        checkResult("Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT",
                     -1, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
        checkResult("Bidi.DIRECTION_LEFT_TO_RIGHT",
                     0, Bidi.DIRECTION_LEFT_TO_RIGHT);
        checkResult("Bidi.DIRECTION_RIGHT_TO_LEFT",
                     1, Bidi.DIRECTION_RIGHT_TO_LEFT);
    }

    private void testConstructors() {
        System.out.println("*** Test constructors");

        testConstructor1();  // Bidi(AttributedCharacterIterator)
        testConstructor2();  // Bidi(String, int)
        testConstructor3();  // Bidi(char[], ...)
    }

    private void testMethods() {
        System.out.println("*** Test methods");

        testMethod_createLineBidi1();
        testMethod_createLineBidi2();
        testMethod_getLevelAt();
        testMethod_getRunLevel();
        testMethod_getRunLimit();
        testMethod_getRunStart();
        testMethod_reorderVisually1();
        testMethod_reorderVisually2();
        testMethod_requiresBidi();
    }

    private void testMethods4Constructor1() {
        System.out.println("*** Test methods for constructor 1");

        String paragraph;
        Bidi bidi;
        NumericShaper ns = NumericShaper.getShaper(NumericShaper.ARABIC);

        for (int textNo = 0; textNo < data4Constructor1.length; textNo++) {
            paragraph = data4Constructor1[textNo][0];
            int start = paragraph.indexOf('<')+1;
            int limit = paragraph.indexOf('>');
            int testNo;

            System.out.println("*** Test textNo=" + textNo +
                ": Bidi(AttributedCharacterIterator\"" +
                toReadableString(paragraph) + "\") " +
                "  start=" + start + ", limit=" + limit);

            // Test 0
            testNo = 0;
            System.out.println(" Test#" + testNo +": RUN_DIRECTION_LTR");
            AttributedString astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_LTR);
            bidi = new Bidi(astr.getIterator());

            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 1
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(1)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_LTR);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
                              start, limit);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 2
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIERCTION_LTR, BIDI_EMBEDDING(2)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_LTR);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
                              start, limit);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 3
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTIOIN_LTR, BIDI_EMBEDDING(-3)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_LTR);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
                              start, limit);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 4
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(-4)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_LTR);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
                              start, limit);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 5
            ++testNo;
            System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_RTL);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 6
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(1)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_RTL);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
                              start, limit);
            try {
                bidi = new Bidi(astr.getIterator());
                callTestEachMethod4Constructor1(textNo, testNo, bidi);
            }
            catch (IllegalArgumentException e) {
                errorHandling("  Unexpected exception: " + e);
            }

            // Test 7
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(2)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_RTL);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
                              start, limit);
            try {
                bidi = new Bidi(astr.getIterator());
                callTestEachMethod4Constructor1(textNo, testNo, bidi);
            }
            catch (IllegalArgumentException e) {
                errorHandling("  Unexpected exception: " + e);
            }

            // Test 8
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-3)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_RTL);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
                              start, limit);
            try {
                bidi = new Bidi(astr.getIterator());
                callTestEachMethod4Constructor1(textNo, testNo, bidi);
            }
            catch (IllegalArgumentException e) {
                errorHandling("  Unexpected exception: " + e);
            }

            // Test 9
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-4)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_RTL);
            astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
                              start, limit);
            try {
                bidi = new Bidi(astr.getIterator());
                callTestEachMethod4Constructor1(textNo, testNo, bidi);
            }
            catch (IllegalArgumentException e) {
                errorHandling("  Unexpected exception: " + e);
            }

            // Test 10
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": TextAttribute not specified");
            astr = new AttributedString(paragraph);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 11
            ++testNo;
            System.out.println(" Test#" + testNo +
                ": RUN_DIRECTION_LTR, NUMERIC_SHAPING(ARABIC)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_LTR);
            astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);

            // Test 12
            ++testNo;
            System.out.println(" Test#" + testNo +
                 ": RUN_DIRECTION_RTL, NUMERIC_SHAPING(ARABIC)");
            astr = new AttributedString(paragraph);
            astr.addAttribute(TextAttribute.RUN_DIRECTION,
                              TextAttribute.RUN_DIRECTION_RTL);
            astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
            bidi = new Bidi(astr.getIterator());
            callTestEachMethod4Constructor1(textNo, testNo, bidi);
        }
    }

    private void testMethods4Constructor2() {
        System.out.println("*** Test methods for constructor 2");

        String paragraph;
        Bidi bidi;

        for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
            paragraph = data4Constructor2[textNo][0];
            for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
                int flag = FLAGS[flagNo];

                System.out.println("*** Test textNo=" + textNo +
                    ": Bidi(\"" + toReadableString(paragraph) +
                    "\", " + getFlagName(flag) + ")");

                bidi = new Bidi(paragraph, flag);
                callTestEachMethod4Constructor2(textNo, flagNo, bidi);
            }
        }
    }

    private void testMethods4Constructor3() {
        System.out.println("*** Test methods for constructor 3");

        String paragraph;
        Bidi bidi;

        for (int textNo = 0; textNo < data4Constructor3.length; textNo++) {
            paragraph = data4Constructor3[textNo][0];
            char[] c = paragraph.toCharArray();
            int start = paragraph.indexOf('<')+1;
            byte[][] embeddings = (c.length < emb4Constructor3[1][0].length) ?
                                  emb4Constructor3[0] : emb4Constructor3[1];
            for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
                int flag = FLAGS[flagNo];
                for (int embNo = 0; embNo < embeddings.length; embNo++) {
                    int dataNo = flagNo * FLAGS.length + embNo;

                    System.out.println("*** Test textNo=" + textNo +
                        ": Bidi(char[]\"" + toReadableString(paragraph) +
                        "\", 0, embeddings={" + toString(embeddings[embNo]) +
                        "}, " + c.length + ", " +
                       getFlagName(flag) + ")" + "  dataNo=" + dataNo);

                    try {
                        bidi = new Bidi(c, 0, embeddings[embNo], 0,
                                        c.length, flag);
                        callTestEachMethod4Constructor3(textNo, dataNo, bidi);
                    }
                    catch (Exception e) {
                        errorHandling("  Unexpected exception: " + e);
                    }
                }
            }
        }
    }

    private void testConstructor1() {
        Bidi bidi;

        try {
            bidi = new Bidi(null);
            errorHandling("Bidi((AttributedCharacterIterator)null) " +
                "should throw an IAE.");
        }
        catch (IllegalArgumentException e) {
        }
        catch (NullPointerException e) {
            errorHandling("Bidi((AttributedCharacterIterator)null) " +
                "should not throw an NPE but an IAE.");
        }

        String paragraph = data4Constructor1[1][0];
        int start = paragraph.indexOf('<')+1;
        int limit = paragraph.indexOf('>');
        AttributedString astr = new AttributedString(paragraph);
        astr.addAttribute(TextAttribute.RUN_DIRECTION,
                          TextAttribute.RUN_DIRECTION_RTL);
        astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-61),
                          start, limit);
        try {
            bidi = new Bidi(astr.getIterator());
            for (int i = start; i < limit; i++) {
                if (bidi.getLevelAt(i) != 61) {
                    errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
                        i + ") should not be " + bidi.getLevelAt(i) +
                        " but 60 when BIDI_EMBEDDING is -61.");
                }
            }
        }
        catch (Exception e) {
            errorHandling("  Unexpected exception: " + e);
        }

        astr = new AttributedString(paragraph);
        astr.addAttribute(TextAttribute.RUN_DIRECTION,
                          TextAttribute.RUN_DIRECTION_RTL);
        astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-62),
                          start, limit);
        try {
            bidi = new Bidi(astr.getIterator());
            for (int i = start; i < limit; i++) {
                if (bidi.getLevelAt(i) != 1) {
                    errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
                        "should be 1 when BIDI_EMBEDDING is -62.");
                }
            }
        }
        catch (Exception e) {
            errorHandling("  Unexpected exception: " + e);
        }

        astr = new AttributedString(paragraph);
        astr.addAttribute(TextAttribute.RUN_DIRECTION,
                          TextAttribute.RUN_DIRECTION_RTL);
        astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(60),
                          start, limit);
        try {
            bidi = new Bidi(astr.getIterator());
            for (int i = start; i < limit; i++) {
                if (bidi.getLevelAt(i) != 61) {
                    errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
                        "should be 61 when BIDI_EMBEDDING is 60.");
                }
            }
        }
        catch (Exception e) {
            errorHandling("  Unexpected exception: " + e);
        }

        astr = new AttributedString(paragraph);
        astr.addAttribute(TextAttribute.RUN_DIRECTION,
                          TextAttribute.RUN_DIRECTION_RTL);
        astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(61),
                          start, limit);
        try {
            bidi = new Bidi(astr.getIterator());
            for (int i = start; i < limit; i++) {
                if (bidi.getLevelAt(i) != 61) {
                    errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
                        i + ") should not be " + bidi.getLevelAt(i) +
                        " but 61 when BIDI_EMBEDDING is 61.");
                }
            }
        }
        catch (Exception e) {
            errorHandling("  Unexpected exception: " + e);
        }

        astr = new AttributedString(paragraph);
        astr.addAttribute(TextAttribute.RUN_DIRECTION,
                          TextAttribute.RUN_DIRECTION_RTL);
        astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(62),
                          start, limit);
        try {
            bidi = new Bidi(astr.getIterator());
            for (int i = start; i < limit; i++) {
                if (bidi.getLevelAt(i) != 1) {
                    errorHandling("Bidi(AttributedCharacterIterator).getLevelAt()" +
                        " should not be " + bidi.getLevelAt(i) +
                        " but 1 when BIDI_EMBEDDING is 62.");
                }
            }
        }
        catch (Exception e) {
            errorHandling("  Unexpected exception: " + e);
        }
    }

    private void testConstructor2() {
        Bidi bidi;

        try {
            bidi = new Bidi(null, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
            errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT)" +
                " should throw an IAE.");
        }
        catch (IllegalArgumentException e) {
        }
        catch (NullPointerException e) {
            errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT) " +
                "should not throw an NPE but an IAE.");
        }

        try {
            bidi = new Bidi("abc", -3);
        }
        catch (Exception e) {
            errorHandling("Bidi(\"abc\", -3) should not throw an exception: " +
                e);
        }

        try {
            bidi = new Bidi("abc", 2);
        }
        catch (Exception e) {
            errorHandling("Bidi(\"abc\", 2) should not throw an exception: " +
                e);
        }
    }

    private void testConstructor3() {
        char[] text = {'a', 'b', 'c', 'd', 'e'};
        byte[] embeddings = {0, 0, 0, 0, 0};
        Bidi bidi;

        try {
            bidi = new Bidi(null, 0, embeddings, 0, 5,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            errorHandling("Bidi(char[], ...) should throw an IAE " +
                "when text=null.");
        }
        catch (IllegalArgumentException e) {
        }
        catch (NullPointerException e) {
            errorHandling("Bidi(char[], ...) should not throw an NPE " +
                "but an IAE when text=null.");
        }

        try {
            bidi = new Bidi(text, -1, embeddings, 0, 5,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            errorHandling("Bidi(char[], ...) should throw an IAE " +
                "when textStart is incorrect(-1: too small).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("Bidi(char[], ...) should not throw an NPE " +
                "but an IAE when textStart is incorrect(-1: too small).");
        }

        try {
            bidi = new Bidi(text, 4, embeddings, 0, 2,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            errorHandling("Bidi(char[], ...) should throw an IAE " +
                "when textStart is incorrect(4: too large).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("Bidi(char[], ...) should not throw an NPE " +
                "but an IAE when textStart is incorrect(4: too large).");
        }

        byte[] actualLevels = new byte[text.length];
        byte[] validEmbeddings1 = {0, -61, -60, -2, -1};
        byte[] expectedLevels1  = {0,  61,  60,  2,  1};
        try {
            bidi = new Bidi(text, 0, validEmbeddings1, 0, 5,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            for (int i = 0; i < text.length; i++) {
                actualLevels[i] = (byte)bidi.getLevelAt(i);
            }
            if (!Arrays.equals(expectedLevels1, actualLevels)) {
                errorHandling("Bidi(char[], ...).getLevelAt()" +
                    " should be {" + toString(actualLevels) +
                    "} when embeddings are {" +
                    toString(expectedLevels1) + "}.");
            }
        }
        catch (Exception e) {
            errorHandling("Bidi(char[], ...) should not throw an exception " +
                "when embeddings is valid(-61).");
        }

        byte[] validEmbeddings2 = {0,  61,  60,  2,  1};
        byte[] expectedLevels2  = {0,  62,  60,  2,  2};
        try {
            bidi = new Bidi(text, 0, validEmbeddings2, 0, 5,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            for (int i = 0; i < text.length; i++) {
                actualLevels[i] = (byte)bidi.getLevelAt(i);
            }
            if (!Arrays.equals(expectedLevels2, actualLevels)) {
                errorHandling("Bidi(char[], ...).getLevelAt()" +
                    " should be {" + toString(actualLevels) +
                    "} when embeddings are {" +
                    toString(expectedLevels2) + "}.");
            }
        }
        catch (Exception e) {
            errorHandling("Bidi(char[], ...) should not throw an exception " +
                "when embeddings is valid(61).");
        }

        byte[] invalidEmbeddings1 = {0, -62, 0, 0, 0};
        try {
            bidi = new Bidi(text, 0, invalidEmbeddings1, 0, 5,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            if (bidi.getLevelAt(1) != 0) {
                errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
                    "when embeddings[1] is -62.");
            }
        }
        catch (Exception e) {
            errorHandling("Bidi(char[], ...) should not throw an exception " +
                "even when embeddings includes -62.");
        }

        byte[] invalidEmbeddings2 = {0, 62, 0, 0, 0};
        try {
            bidi = new Bidi(text, 0, invalidEmbeddings2, 0, 5,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            if (bidi.getLevelAt(1) != 0) {
                errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
                    "when embeddings[1] is 62.");
            }
        }
        catch (Exception e) {
            errorHandling("Bidi(char[], ...) should not throw an exception " +
                "even when embeddings includes 62.");
        }

        try {
            bidi = new Bidi(text, 0, embeddings, 0, -1,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            errorHandling("Bidi(char[], ...) should throw an IAE " +
                "when paragraphLength=-1(too small).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (NegativeArraySizeException e) {
            errorHandling("Bidi(char[], ...) should not throw an NASE " +
                "but an IAE when paragraphLength=-1(too small).");
        }

        try {
            bidi = new Bidi(text, 0, embeddings, 0, 6,
                            Bidi.DIRECTION_LEFT_TO_RIGHT);
            errorHandling("Bidi(char[], ...) should throw an IAE " +
                "when paragraphLength=6(too large).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("Bidi(char[], ...) should not throw an AIOoBE " +
                "but an IAE when paragraphLength=6(too large).");
        }

        try {
            bidi = new Bidi(text, 0, embeddings, 0, 4, -3);
        }
        catch (Exception e) {
            errorHandling("Bidi(char[], ...) should not throw an exception " +
                "even when flag=-3(too small).");
        }

        try {
            bidi = new Bidi(text, 0, embeddings, 0, 5, 2);
        }
        catch (Exception e) {
            errorHandling("Bidi(char[], ...) should not throw an exception " +
                "even when flag=2(too large).");
        }
    }

    private void callTestEachMethod4Constructor1(int textNo,
                                                 int testNo,
                                                 Bidi bidi) {
        testEachMethod(bidi,
                       data4Constructor1[textNo][0],
                       data4Constructor1[textNo][testNo+1],
                       baseIsLTR4Constructor1[textNo][testNo],
                       isLTR_isRTL4Constructor1[textNo][0][testNo],
                       isLTR_isRTL4Constructor1[textNo][1][testNo]);
    }

    private void callTestEachMethod4Constructor2(int textNo,
                                                 int flagNo,
                                                 Bidi bidi) {
        testEachMethod(bidi,
                       data4Constructor2[textNo][0],
                       data4Constructor2[textNo][flagNo+1],
                       baseIsLTR4Constructor2[textNo][flagNo],
                       isLTR_isRTL4Constructor2[textNo][0][flagNo],
                       isLTR_isRTL4Constructor2[textNo][1][flagNo]);
    }

    private void callTestEachMethod4Constructor3(int textNo,
                                                 int dataNo,
                                                 Bidi bidi) {
        testEachMethod(bidi,
                       data4Constructor3[textNo][0],
                       data4Constructor3[textNo][dataNo+1],
                       baseIsLTR4Constructor3[textNo][dataNo],
                       isLTR_isRTL4Constructor3[textNo][0][dataNo],
                       isLTR_isRTL4Constructor3[textNo][1][dataNo]);
    }

    private StringBuilder sb = new StringBuilder();
    private void testEachMethod(Bidi bidi,
                                String text,
                                String expectedLevels,
                                boolean expectedBaseIsLTR,
                                boolean expectedIsLTR,
                                boolean expectedIsRTL
                               ) {
        /* Test baseIsLeftToRight() */
        boolean actualBoolean = bidi.baseIsLeftToRight();
        checkResult("baseIsLeftToRight()", expectedBaseIsLTR, actualBoolean);

        /* Test getBaseLevel() */
        int expectedInt = (expectedBaseIsLTR) ? 0 : 1;
        int actualInt = bidi.getBaseLevel();
        checkResult("getBaseLevel()", expectedInt, actualInt);

        /* Test getLength() */
        expectedInt = text.length();
        actualInt = bidi.getLength();
        checkResult("getLength()", expectedInt, actualInt);

        /* Test getLevelAt() */
        sb.setLength(0);
        for (int i = 0; i < text.length(); i++) {
            sb.append(bidi.getLevelAt(i));
        }
        checkResult("getLevelAt()", expectedLevels, sb.toString());

        /* Test getRunCount() */
        expectedInt = getRunCount(expectedLevels);
        actualInt = bidi.getRunCount();
        checkResult("getRunCount()", expectedInt, actualInt);

        /* Test getRunLevel(), getRunLimit() and getRunStart() */
        if (expectedInt == actualInt) {
            int runCount = expectedInt;
            int[] expectedRunLevels = getRunLevels_int(runCount, expectedLevels);
            int[] expectedRunLimits = getRunLimits(runCount, expectedLevels);
            int[] expectedRunStarts = getRunStarts(runCount, expectedLevels);
            int[] actualRunLevels = new int[runCount];
            int[] actualRunLimits = new int[runCount];
            int[] actualRunStarts = new int[runCount];

            for (int k = 0; k < runCount; k++) {
                actualRunLevels[k] = bidi.getRunLevel(k);
                actualRunLimits[k] = bidi.getRunLimit(k);
                actualRunStarts[k] = bidi.getRunStart(k);
            }

            checkResult("getRunLevel()", expectedRunLevels, actualRunLevels);
            checkResult("getRunStart()", expectedRunStarts, actualRunStarts);
            checkResult("getRunLimit()", expectedRunLimits, actualRunLimits);
        }

        /* Test isLeftToRight() */
        boolean expectedBoolean = expectedIsLTR;
        actualBoolean = bidi.isLeftToRight();
        checkResult("isLeftToRight()", expectedBoolean, actualBoolean);

        /* Test isMixed() */
        expectedBoolean = !(expectedIsLTR || expectedIsRTL);
        actualBoolean = bidi.isMixed();
        checkResult("isMixed()", expectedBoolean, actualBoolean);

        /* Test isRightToLeft() */
        expectedBoolean = expectedIsRTL;
        actualBoolean = bidi.isRightToLeft();
        checkResult("isRightToLeft()", expectedBoolean, actualBoolean);
    }

    private int getRunCount(String levels) {
        int len = levels.length();
        char c = levels.charAt(0);
        int runCount = 1;

        for (int index = 1; index < len; index++) {
            if (levels.charAt(index) != c) {
                runCount++;
                c = levels.charAt(index);
            }
        }

        return runCount;
    }

    private int[] getRunLevels_int(int runCount, String levels) {
        int[] array = new int[runCount];
        int len = levels.length();
        char c = levels.charAt(0);
        int i = 0;
        array[i++] = c - '0';

        for (int index = 1; index < len; index++) {
            if (levels.charAt(index) != c) {
                c = levels.charAt(index);
                array[i++] = c - '0';
            }
        }

        return array;
    }

    private byte[] getRunLevels_byte(int runCount, String levels) {
        byte[] array = new byte[runCount];
        int len = levels.length();
        char c = levels.charAt(0);
        int i = 0;
        array[i++] = (byte)(c - '0');

        for (int index = 1; index < len; index++) {
            if (levels.charAt(index) != c) {
                c = levels.charAt(index);
                array[i++] = (byte)(c - '0');
            }
        }

        return array;
    }

    private int[] getRunLimits(int runCount, String levels) {
        int[] array = new int[runCount];
        int len = levels.length();
        char c = levels.charAt(0);
        int i = 0;

        for (int index = 1; index < len; index++) {
            if (levels.charAt(index) != c) {
                c = levels.charAt(index);
                array[i++] = index;
            }
        }
        array[i] = len;

        return array;
    }

    private int[] getRunStarts(int runCount, String levels) {
        int[] array = new int[runCount];
        int len = levels.length();
        char c = levels.charAt(0);
        int i = 1;

        for (int index = 1; index < len; index++) {
            if (levels.charAt(index) != c) {
                c = levels.charAt(index);
                array[i++] = index;
            }
        }

        return array;
    }

    private String[] getObjects(int runCount, String text, String levels) {
        String[] array = new String[runCount];
        int[] runLimits = getRunLimits(runCount, levels);
        int runStart = 0;

        for (int i = 0; i < runCount; i++) {
            array[i] = text.substring(runStart, runLimits[i]);
            runStart = runLimits[i];
        }

        return array;
    }

    private void testMethod_createLineBidi1() {
        System.out.println("*** Test createLineBidi() 1");

        String str = " ABC 123. " + HebrewABC + " " + NKo123 + ". ABC 123";

        int lineStart = str.indexOf('.') + 2;
        int lineLimit = str.lastIndexOf('.') + 2;
        Bidi bidi = new Bidi(str, FLAGS[0]);
        Bidi lineBidi = bidi.createLineBidi(lineStart, lineLimit);

        checkResult("getBaseLevel()",
            bidi.getBaseLevel(), lineBidi.getBaseLevel());
        checkResult("getLevelAt(5)",
            bidi.getLevelAt(lineStart+5), lineBidi.getLevelAt(5));
    }

    private void testMethod_createLineBidi2() {
        System.out.println("*** Test createLineBidi() 2");

        Bidi bidi = new Bidi(data4Constructor1[0][0], FLAGS[0]);
        int len = data4Constructor1[0][0].length();

        try {
            Bidi lineBidi = bidi.createLineBidi(0, len);
        }
        catch (Exception e) {
            errorHandling("createLineBidi(0, textLength)" +
                " should not throw an exception.");
        }

        try {
            Bidi lineBidi = bidi.createLineBidi(-1, len);
            errorHandling("createLineBidi(-1, textLength)" +
                " should throw an IAE.");
        }
        catch (IllegalArgumentException e) {
        }

        try {
            Bidi lineBidi = bidi.createLineBidi(0, len+1);
            errorHandling("createLineBidi(0, textLength+1)" +
                " should throw an IAE.");
        }
        catch (IllegalArgumentException e) {
        }
    }

    /*
     * Confirm that getLevelAt() doesn't throw an exception for invalid offset
     * unlike ICU4J.
     */
    private void testMethod_getLevelAt() {
        System.out.println("*** Test getLevelAt()");

        Bidi bidi = new Bidi(data4Constructor1[1][0], FLAGS[0]);
        int len = data4Constructor1[1][0].length();

        try {
            int level = bidi.getLevelAt(-1);
            if (level != bidi.getBaseLevel()) {
                errorHandling("getLevelAt(-1) returned a wrong level." +
                    " Expected=" + bidi.getBaseLevel() + ", got=" + level);
            }
        }
        catch (Exception e) {
            errorHandling("getLevelAt(-1) should not throw an exception.");
        }

        try {
            int level = bidi.getLevelAt(len+1);
            if (level != bidi.getBaseLevel()) {
                errorHandling("getLevelAt(textLength+1)" +
                    " returned a wrong level." +
                    " Expected=" + bidi.getBaseLevel() + ", got=" + level);
            }
        }
        catch (Exception e) {
            errorHandling("getLevelAt(-1) should not throw an exception.");
        }
    }

    private void testMethod_getRunLevel() {
        System.out.println("*** Test getRunLevel()");

        String str = "ABC 123";
        Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
        try {
            if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 0 ||   // runCount - 1
                bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = "ABC " + HebrewABC + " 123";
        bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
        try {
            if (bidi.getRunLevel(-1) != 0 ||  // runCount - 4 (out of range)
                bidi.getRunLevel(0) != 0 ||   // runCount - 3
                bidi.getRunLevel(1) != 1 ||   // runCount - 2
                bidi.getRunLevel(2) != 2 ||   // runCount - 1
                bidi.getRunLevel(3) != 0 ||   // runCount     (out of range)
                bidi.getRunLevel(4) != 0) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = "ABC";
        bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
        try {
            if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 0 ||   // runCount - 1
                bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = "ABC";
        bidi = new Bidi(str, Bidi.DIRECTION_RIGHT_TO_LEFT);
        try {
            if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 2 ||   // runCount - 1
                bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = "ABC";
        bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        try {
            if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 0 ||   // runCount - 1
                bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = "ABC";
        bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
        try {
            if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 0 ||   // runCount - 1
                bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = HebrewABC;
        bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
        try {
            if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 1 ||   // runCount - 1
                bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = HebrewABC;
        bidi = new Bidi(str, Bidi.DIRECTION_RIGHT_TO_LEFT);
        try {
            if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 1 ||   // runCount - 1
                bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = HebrewABC;
        bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        try {
            if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 1 ||   // runCount - 1
                bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }

        str = HebrewABC;
        bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
        try {
            if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
                bidi.getRunLevel(0) != 1 ||   // runCount - 1
                bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
                bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
                errorHandling("Incorrect getRunLevel() value(s).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLevel() should not throw an exception: " + e);
        }
    }

    private void testMethod_getRunLimit() {
        System.out.println("*** Test getRunLimit()");

        String str = "ABC 123";
        int length = str.length();
        Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);

        try {
            if (bidi.getRunLimit(-1) != length ||  // runCount - 2
                bidi.getRunLimit(0) != length ||   // runCount - 1
                bidi.getRunLimit(1) != length ||   // runCount
                bidi.getRunLimit(2) != length) {   // runCount + 1
                errorHandling("getRunLimit() should return " + length +
                    " when getRunCount() is 1.");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLimit() should not throw an exception " +
                "when getRunCount() is 1.");
        }

        str = "ABC " + ArabicABC + " 123";
        length = str.length();
        bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);

        try {
            bidi.getRunLimit(-1);
            errorHandling("getRunLimit() should throw an AIOoBE " +
                "when run is -1(too small).");
        }
        catch (ArrayIndexOutOfBoundsException e) {
        }
        catch (IllegalArgumentException e) {
            errorHandling("getRunLimit() should not throw an IAE " +
                "but an AIOoBE when run is -1(too small).");
        }

        try {
            bidi.getRunLimit(0);
            bidi.getRunLimit(1);
            bidi.getRunLimit(2);
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("getRunLimit() should not throw an AIOOBE " +
                "when run is from 0 to 2(runCount-1).");
        }

        try {
            bidi.getRunLimit(3);
            errorHandling("getRunLimit() should throw an AIOoBE " +
                "when run is 3(same as runCount).");
        }
        catch (ArrayIndexOutOfBoundsException e) {
        }
        catch (IllegalArgumentException e) {
            errorHandling("getRunLimit() should not throw an IAE " +
                "but an AIOoBE when run is 3(same as runCount).");
        }
    }

    private void testMethod_getRunStart() {
        System.out.println("*** Test getRunStart()");

        String str = "ABC 123";
        int length = str.length();
        Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);

        try {
            if (bidi.getRunStart(-1) != 0 ||  // runCount - 2
                bidi.getRunStart(0) != 0 ||   // runCount - 1
                bidi.getRunStart(1) != 0 ||   // runCount
                bidi.getRunStart(2) != 0) {   // runCount + 1
                errorHandling("getRunStart() should return 0" +
                    " when getRunCount() is 1.");
            }
        }
        catch (Exception e) {
            errorHandling("getRunLimit() should not throw an exception" +
                " when getRunCount() is 1.");
        }

        str = "ABC " + NKoABC + " 123";
        length = str.length();
        bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);

        try {
            bidi.getRunStart(-1);
            errorHandling("getRunStart() should throw an AIOoBE" +
                " when run is -1(too small).");
        }
        catch (ArrayIndexOutOfBoundsException e) {
        }
        catch (IllegalArgumentException e) {
            errorHandling("getRunStart() should not throw an IAE " +
                "but an AIOoBE when run is -1(too small).");
        }

        try {
            bidi.getRunStart(0);
            bidi.getRunStart(1);
            bidi.getRunStart(2);
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("getRunStart() should not throw an AIOOBE " +
                "when run is from 0 to 2(runCount-1).");
        }

        try {
            if (bidi.getRunStart(3) != length) {
                errorHandling("getRunStart() should return " + length +
                    " when run is 3(same as runCount).");
            }
        }
        catch (Exception e) {
            errorHandling("getRunStart() should not throw an exception " +
                "when run is 3(same as runCount).");
        }

        try {
            bidi.getRunStart(4);
            errorHandling("getRunStart() should throw an AIOoBE " +
                "when run is runCount+1(too large).");
        }
        catch (ArrayIndexOutOfBoundsException e) {
        }
        catch (IllegalArgumentException e) {
            errorHandling("getRunStart() should not throw an IAE " +
                "but an AIOoBE when run is runCount+1(too large).");
        }
    }

    private void testMethod_reorderVisually1() {
        System.out.println("*** Test reorderVisually() 1");

        for (int textNo = 0; textNo < data4reorderVisually.length; textNo++) {
            Object[] objects = data4reorderVisually[textNo][0];
            byte[] levels = getLevels(data4reorderVisually[textNo]);
            Object[] expectedObjects = data4reorderVisually[textNo][2];

            Bidi.reorderVisually(levels, 0, objects, 0, objects.length);

            checkResult("textNo=" + textNo + ": reorderVisually(levels=[" +
                toString(levels) + "], objects=[" + toString(objects) + "])",
                expectedObjects, objects);
        }
    }

    private void testMethod_reorderVisually2() {
        System.out.println("*** Test reorderVisually() 2");

        Object[] objects = data4reorderVisually[0][0];
        byte[] levels = getLevels(data4reorderVisually[0]);
        int count = objects.length;
        int llen = levels.length;
        int olen = objects.length;

        try {
            Bidi.reorderVisually(null, 0, objects, 0, count);
            errorHandling("reorderVisually() should throw a NPE " +
                "when levels is null.");
        }
        catch (NullPointerException e) {
        }

        try {
            Bidi.reorderVisually(levels, -1, objects, 0, count);
            errorHandling("reorderVisually() should throw an IAE " +
                "when levelStart is -1.");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("reorderVisually() should not throw an AIOoBE " +
                "but an IAE when levelStart is -1.");
        }

        try {
            Bidi.reorderVisually(levels, llen, objects, 0, count);
            errorHandling("reorderVisually() should throw an IAE " +
                "when levelStart is 6(levels.length).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("reorderVisually() should not throw an AIOoBE " +
                "but an IAE when levelStart is 6(levels.length).");
        }

        try {
            Bidi.reorderVisually(levels, 0, null, 0, count);
            errorHandling("reorderVisually() should throw a NPE" +
                " when objects is null.");
        }
        catch (NullPointerException e) {
        }

        try {
            Bidi.reorderVisually(levels, 0, objects, -1, count);
            errorHandling("reorderVisually() should throw an IAE" +
                " when objectStart is -1.");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("reorderVisually() should not throw an AIOoBE " +
                "but an IAE when objectStart is -1.");
        }

        try {
            Bidi.reorderVisually(levels, 0, objects, 6, objects.length);
            errorHandling("reorderVisually() should throw an IAE " +
                "when objectStart is 6(objects.length).");
        }
        catch (IllegalArgumentException e) {
        }

        try {
            Bidi.reorderVisually(levels, 0, objects, 0, -1);
            errorHandling("reorderVisually() should throw an IAE " +
                "when count is -1.");
        }
        catch (IllegalArgumentException e) {
        }
        catch (NegativeArraySizeException e) {
            errorHandling("reorderVisually() should not throw an NASE " +
                "but an IAE when count is -1.");
        }

        try {
            Bidi.reorderVisually(levels, 0, objects, 0, count+1);
            errorHandling("reorderVisually() should throw an IAE " +
                "when count is 7(objects.length+1).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("reorderVisually() should not throw an AIOoBE " +
                "but an IAE when count is 7(objects.length+1).");
        }

        try {
            Bidi.reorderVisually(levels, 0, objects, 0, 0);
            checkResult("reorderVisually(count=0)",
                data4reorderVisually[0][0], objects);
        }
        catch (Exception e) {
            errorHandling("reorderVisually() should not throw an exception" +
                " when count is 0.");
        }
    }

    private void testMethod_requiresBidi() {
        System.out.println("*** Test requiresBidi()");

        String paragraph;
        char[] text;
        Bidi bidi;

        for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
            paragraph = data4Constructor2[textNo][0];
            text = paragraph.toCharArray();
            boolean rBidi = Bidi.requiresBidi(text, 0, text.length);
            if (rBidi != requiresBidi4Constructor2[textNo]) {
                error = true;
                System.err.println("Unexpected requiresBidi() value" +
                    " for requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
                    text.length + ")." +
                    "\n    Expected: " + requiresBidi4Constructor2[textNo] +
                    "\n    Got     : " + rBidi);
            } else if (verbose) {
                System.out.println("  Okay : requiresBidi() for" +
                    " requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
                    text.length + ")  Got: " + rBidi);
            }
        }

        char[] txt = {'A', 'B', 'C', 'D', 'E'};
        int textLength = txt.length;

        try {
            Bidi.requiresBidi(txt, -1, textLength);
            errorHandling("requiresBidi() should throw an IAE" +
                " when start is -1(too small).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("requiresBidi() should not throw an AIOoBE " +
                "but an IAE when start is -1(too small).");
        }

        try {
            Bidi.requiresBidi(txt, textLength, textLength);
        }
        catch (Exception e) {
            errorHandling("requiresBidi() should not throw an exception " +
                "when start is textLength.");
        }

        try {
            Bidi.requiresBidi(txt, textLength+1, textLength);
            errorHandling("requiresBidi() should throw an IAE" +
                " when start is textLength+1(too large).");
        }
        catch (IllegalArgumentException e) {
        }

        try {
            Bidi.requiresBidi(txt, 0, -1);
            errorHandling("requiresBidi() should throw an IAE" +
                " when limit is -1(too small).");
        }
        catch (IllegalArgumentException e) {
        }

        try {
            Bidi.requiresBidi(txt, 0, textLength+1);
            errorHandling("requiresBidi() should throw an IAE" +
                " when limit is textLength+1(too large).");
        }
        catch (IllegalArgumentException e) {
        }
        catch (ArrayIndexOutOfBoundsException e) {
            errorHandling("requiresBidi() should not throw an AIOoBE " +
                "but an IAE when limit is textLength+1(too large).");
        }
    }

    private void checkResult(String name,
                             int expectedValue,
                             int actualValue) {
        if (expectedValue != actualValue) {
            errorHandling("Unexpected " + name + " value." +
                " Expected: " + expectedValue + " Got: " + actualValue);
        } else if (verbose) {
            System.out.println("  Okay : " + name + " = " + actualValue);
        }
    }

    private void checkResult(String name,
                             boolean expectedValue,
                             boolean actualValue) {
        if (expectedValue != actualValue) {
            errorHandling("Unexpected " + name + " value." +
                " Expected: " + expectedValue + " Got: " + actualValue);
        } else if (verbose) {
            System.out.println("  Okay : " + name + " = " + actualValue);
        }
    }

    private void checkResult(String name,
                             String expectedValue,
                             String actualValue) {
        if (!expectedValue.equals(actualValue)) {
            errorHandling("Unexpected " + name + " value." +
                "\n\tExpected: \"" + expectedValue + "\"" +
                "\n\tGot:      \"" + actualValue + "\"");
        } else if (verbose) {
            System.out.println("  Okay : " + name + " = \"" +
                actualValue + "\"");
        }
    }

    private void checkResult(String name,
                             int[] expectedValues,
                             int[] actualValues) {
        if (!Arrays.equals(expectedValues, actualValues)) {
            errorHandling("Unexpected " + name + " value." +
                "\n\tExpected: " + toString(expectedValues) + "" +
                "\n\tGot:      " + toString(actualValues) + "");
        } else if (verbose) {
            System.out.println("  Okay : " + name + " = " +
                toString(actualValues));
        }
    }

    private void checkResult(String name,
                             Object[] expectedValues,
                             Object[] actualValues) {
        if (!Arrays.equals(expectedValues, actualValues)) {
            errorHandling("Unexpected " + name + " value." +
                "\n\tExpected: [" + toString(expectedValues) +
                "]\n\tGot:      [" + toString(actualValues) + "]");
        } else if (verbose) {
            System.out.println("  Okay : " + name + " Reordered objects = [" +
                toString(actualValues) + "]");
        }
    }

    private void errorHandling(String msg) {
        if (abort) {
            throw new RuntimeException("Error: " + msg);
        } else {
            error = true;
            System.err.println("**Error:" + msg);
        }
    }

    private String toString(int[] values) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length-1; i++) {
            sb.append((int)values[i]);
            sb.append(' ');
        }
        sb.append((int)values[values.length-1]);

        return sb.toString();
    }

    private String toString(byte[] values) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length-1; i++) {
            sb.append((byte)values[i]);
            sb.append(' ');
        }
        sb.append((byte)values[values.length-1]);

        return sb.toString();
    }

    private String toString(Object[] values) {
        StringBuilder sb = new StringBuilder();
        String name;

        for (int i = 0; i < values.length-1; i++) {
            if ((name = getStringName((String)values[i])) != null) {
                sb.append(name);
                sb.append(", ");
            } else {
                sb.append('"');
                sb.append((String)values[i]);
                sb.append("\", ");
            }
        }
        if ((name = getStringName((String)values[values.length-1])) != null) {
            sb.append(name);
        } else {
            sb.append('"');
            sb.append((String)values[values.length-1]);
            sb.append('\"');
        }

        return sb.toString();
    }

    private String getStringName(String str) {
        if (ArabicABC.equals(str)) return "ArabicABC";
        else if (Arabic123.equals(str)) return "Arabic123";
        else if (PArabicABC.equals(str)) return "ArabicABC(Presentation form)";
        else if (HebrewABC.equals(str)) return "HebrewABC";
        else if (KharoshthiABC.equals(str)) return "KharoshthiABC(RTL)";
        else if (Kharoshthi123.equals(str)) return "Kharoshthi123(RTL)";
        else if (NKoABC.equals(str)) return "NKoABC(RTL)";
        else if (NKo123.equals(str)) return "NKo123(RTL)";
        else if (OsmanyaABC.equals(str)) return "OsmanyaABC(LTR)";
        else if (Osmanya123.equals(str)) return "Osmanya123(LTR)";
        else return null;
    }

    private String getFlagName(int flag) {
        if (flag == -2 || flag == 0x7e) return FLAGNAMES[0];
        else if (flag == -1 || flag == 0x7f) return FLAGNAMES[1];
        else if (flag == 0) return FLAGNAMES[2];
        else if (flag == 1) return FLAGNAMES[3];
        else return "Unknown(0x" + Integer.toHexString(flag) + ")";
    }

    private String toReadableString(String str) {
         String s = str;

         s = s.replaceAll(ArabicABC, "ArabicABC");
         s = s.replaceAll(Arabic123, "Arabic123");
         s = s.replaceAll(PArabicABC, "ArabicABC(Presentation form)");
         s = s.replaceAll(HebrewABC, "HebrewABC");
         s = s.replaceAll(KharoshthiABC, "KharoshthiABC");
         s = s.replaceAll(Kharoshthi123, "Kharoshthi123");
         s = s.replaceAll(NKoABC, "NKoABC");
         s = s.replaceAll(NKo123, "NKo123");
         s = s.replaceAll(OsmanyaABC, "OsmanyaABC");
         s = s.replaceAll(Osmanya123, "Osmanya123");

         return s;
    }

    private  byte[] getLevels(Object[][] data) {
        int levelLength = data[0].length;
        byte[] array = new byte[levelLength];
        int textIndex = 0;

        for (int i = 0; i < levelLength; i++) {
            array[i] = (byte)(((String)data[1][0]).charAt(textIndex) - '0');
            textIndex += ((String)data[0][i]).length();
        }

        return array;
    }


    /* Bidi pubilc constants */
    private static final int[] FLAGS = {
        Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT,  // -2 (0x7e in ICU4J)
        Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT,  // -1 (0x7f in ICU4J)
        Bidi.DIRECTION_LEFT_TO_RIGHT,          //  0
        Bidi.DIRECTION_RIGHT_TO_LEFT           //  1
    };

    /* Bidi pubilc constants names */
    private static final String[] FLAGNAMES = {
        "DIRECTION_DEFAULT_LEFT_TO_RIGHT",  // -2
        "DIRECTION_DEFAULT_RIGHT_TO_LEFT",  // -1
        "DIRECTION_LEFT_TO_RIGHT",          //  0
        "DIRECTION_RIGHT_TO_LEFT",          //  1
    };

    /* Bidirectional Character Types */
    private static final char L   = '\u200E';
    private static final char R   = '\u202F';
    private static final char LRE = '\u202A';
    private static final char RLE = '\u202B';
    private static final char PDF = '\u202C';
    private static final char LRO = '\u202D';
    private static final char RLO = '\u202E';

    /*
     *  0x05D0-0x05EA:   [R]   Hewbrew letters (Strong)
     *  0x0627-0x063A:   [AL]  Arabic letters (Strong)
     *  0x0660-0x0669:   [AN]  Arabic-Indic digits (Weak)
     *  0x07CA-0x07E7:   [R]   NKo letters (Strong)
     *  0x07C0-0x07C9:   [R]   NKo digits (Strong)
     *  0xFE50-0xFEFF:   [AL]  Arabic presentaion form (Strong)
     *  0x10480-0x1049D: [L]   Osmanya letters (Strong)
     *  0x104A0-0x104A9: [L]   Osmanya digits (Strong)
     *  0x10A10-0x10A33: [R]   Kharoshthi letters (Strong)
     *  0x10A40-0x10A43: [R]   Kharoshthi digits (Strong)
     *
     *  0x200E:          [L]   Left-to-right mark (Implicit, Strong)
     *  0x200F:          [R]   Right-to-left mark (Implicit, Strong)
     *  0x202A:          [LRE] Left-to-right embedding (Explicit, Strong)
     *  0x202B:          [RLE] Right-to-left embedding (Explicit, Strong)
     *  0x202C:          [PDF] Pop directional formatting (Explicit, Weak)
     *  0x202D:          [LRO] Left-to-right override (Explicit, Strong)
     *  0x202E:          [RLO] Right-to-left override (Explicit, Strong)
     */

    /* Right-to-left */
    private static String ArabicABC = "\u0627\u0628\u0629";
    private static String Arabic123 = "\u0661\u0662\u0663";
    private static String PArabicABC = "\uFE97\uFE92\uFE8E";
    private static String HebrewABC = "\u05D0\u05D1\u05D2";
    private static String KharoshthiABC =
        new String(Character.toChars(0x10A10)) +
        new String(Character.toChars(0x10A11)) +
        new String(Character.toChars(0x10A12));
    private static String Kharoshthi123 =
        new String(Character.toChars(0x10A40)) +
        new String(Character.toChars(0x10A41)) +
        new String(Character.toChars(0x10A42));
    private static String NKoABC = "\u07CA\u07CB\u07CC";
    private static String NKo123 = "\u07C1\u07C2\u07C3";

    /* Left-to-right */
    private static String OsmanyaABC =
        new String(Character.toChars(0x10480)) +
        new String(Character.toChars(0x10481)) +
        new String(Character.toChars(0x10482));
    private static String Osmanya123 =
        new String(Character.toChars(0x104A0)) +
        new String(Character.toChars(0x104A1)) +
        new String(Character.toChars(0x104A2));

    /* --------------------------------------------------------------------- */

    /*
     * Test data for Bidi(char[], ...) constructor and methods
     */

    /* Text for Bidi processing and its levels */
    private static String[][] data4Constructor1 = {
        /* For Text #0 */
        {"abc <ABC XYZ> xyz.",
             "000000000000000000", "000002222222000000", "000000000000000000",
             "000003333333000000", "000000000000000000",
             "222222222222222221", "222222222222222221", "222222222222222221",
             "222113333333112221", "222224444444222221",
             "000000000000000000", "000000000000000000", "222222222222222221"},

        /* For Text #1 */
        {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
             "000001111111000000", "000001111111000000", "000003333333000000",
             "000003333333000000", "000000000000000000",
             "222111111111112221", "222111111111112221", "222223333333222221",
             "222113333333112221", "222224444444222221",
             "000001111111000000", "000001111111000000", "222111111111112221"},

        /* For Text #2 */
        {NKoABC + " <ABC XYZ> " + NKo123 + ".",
             "111000000000001110", "111112222222111110", "111002222222001110",
             "111113333333111110", "111004444444001110",
             "111112222222111111", "111112222222111111", "111112222222111111",
             "111111111111111111", "111114444444111111",
             "111112222222111111", "111000000000001110", "111112222222111111"},

        /* For Text #3 */
        {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
             "111111111222111110", "111111111222111110", "111003333444001110",
             "111113333333111110", "111004444444001110",
             "111111111222111111", "111111111222111111", "111113333444111111",
             "111111111111111111", "111114444444111111",
             "111111111222111111", "111111111222111110", "111111111222111111"},

        /* For Text #4 */
        {"abc <" + NKoABC + " 123> xyz.",
             "000001111222000000", "000001111222000000", "000003333444000000",
             "000003333333000000", "000000000000000000",
             "222111111222112221", "222111111222112221", "222223333444222221",
             "222113333333112221", "222224444444222221",
             "000001111222000000", "000001111222000000", "222111111222112221"},

        /* For Text #5 */
        {"abc <ABC " + NKo123 + "> xyz.",
             "000000000111000000", "000002221111000000", "000002222333000000",
             "000003333333000000", "000000000000000000",
             "222222221111112221", "222222221111112221", "222222222333222221",
             "222113333333112221", "222224444444222221",
             "000000000111000000", "000000000111000000", "222222221111112221"},

        /* For Text #6 */
        {ArabicABC + " <" + NKoABC + " 123" + "> " + Arabic123 + ".",
             "111111111222112220", "111111111222112220", "111003333444002220",
             "111113333333112220", "111004444444002220",
             "111111111222112221", "111111111222112221", "111113333444112221",
             "111113333333112221", "111114444444112221",
             "111111111222112221", "111111111222112220", "111111111222112221"},

        /* For Text #7 */
        {ArabicABC + " <XYZ " + NKoABC + "> " + Arabic123 + ".",
             "111000000111112220", "111112221111112220", "111002222333002220",
             "111113333333112220", "111004444444002220",
             "111112221111112221", "111112221111112221", "111112222333112221",
             "111113333333112221", "111114444444112221",
             "111112221111112221", "111000000111112220", "111112221111112221"},

        /* For Text #8 */
        {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
         Osmanya123 + ".",
             "000000001111111111111000000000", "000000001111111111111000000000",
             "000000003333333333333000000000", "000000003333333333333000000000",
             "000000000000000000000000000000",
             "222222111111111111111112222221", "222222111111111111111112222221",
             "222222223333333333333222222221", "222222113333333333333112222221",
             "222222224444444444444222222221",
             "000000001111111111111000000000", "000000001111111111111000000000",
             "222222111111111111111112222221"},

        /* For Text #9 */
        {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
         Kharoshthi123 + ".",
             "111111000000000000000001111110", "111111112222222222222111111110",
             "111111002222222222222001111110", "111111113333333333333111111110",
             "111111004444444444444001111110",
             "111111112222222222222111111111", "111111112222222222222111111111",
             "111111112222222222222111111111", "111111111111111111111111111111",
             "111111114444444444444111111111",
             "111111112222222222222111111111", "111111000000000000000001111110",
             "111111112222222222222111111111"},
    };

    /* Golden data for baseIsLeftToRight() results */
    private static boolean[][] baseIsLTR4Constructor1 = {
        /* For Text #0 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         true,  true,  false},

        /* For Text #1 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         true,  true,  false},

        /* For Text #2 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         false, true,  false},

        /* For Text #3 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         false, true,  false},

        /* For Text #4 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         true,  true,  false},

        /* For Text #5 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         true,  true,  false},

        /* For Text #6 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         false, true,  false},

        /* For Text #7 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         false, true,  false},

        /* For Text #8 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         true,  true,  false},

        /* For Text #9 */
        {true,  true,  true,  true,  true,
         false, false, false, false, false,
         false, true,  false},
    };

    /* Golden data for isLeftToRight() & isRightToLeft() results */
    private static boolean[][][] isLTR_isRTL4Constructor1 = {
        /* For Text #0 */
         /* isLeftToRight() results */
        {{true,  false, true,  false, true,
          false, false, false, false, false,
          true,  true,  false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, false, false,
          false, false, false}},

        /* For Text #1 */
         /* isLeftToRight() results */
        {{false, false, false, false, true,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, false, false,
          false, false, false}},

        /* For Text #2 */
         /* isLeftToRight() results */
        {{false, false, false, false, false,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, true,  false,
          false, false, false}},

        /* For Text #3 */
         /* isLeftToRight() results */
        {{false, false, false, false, false,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, true,  false,
          false, false, false}},

        /* For Text #4 */
         /* isLeftToRight() results */
        {{false, false, false, false, true,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, false, false,
          false, false, false}},

        /* For Text #5 */
         /* isLeftToRight() results */
        {{false, false, false, false, true,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, false, false,
          false, false, false}},

        /* For Text #6 */
         /* isLeftToRight() results */
        {{false, false, false, false, false,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, false, false,
          false, false, false}},

        /* For Text #7 */
         /* isLeftToRight() results */
        {{false, false, false, false, false,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, false, false,
          false, false, false}},

        /* For Text #8 */
         /* isLeftToRight() results */
        {{false, false, false, false, true,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, false, false,
          false, false, false}},

        /* For Text #9 */
         /* isLeftToRight() results */
        {{false, false, false, false, false,
          false, false, false, false, false,
          false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false, false,
          false, false, false, true,  false,
          false, false, false}},
    };

    /* --------------------------------------------------------------------- */

    /*
     * Test data for Bidi(String, int) constructor and methods
     */

    /* Text for Bidi processing and its levels */
    private static String[][] data4Constructor2 = {
        /* For Text #0 */
        {" ABC 123.",
             "000000000", "000000000", "000000000", "122222221"},

        /* For Text #1 */
        {" ABC " + HebrewABC + " " + NKo123 + " 123.",
             "00000111111112220", "00000111111112220", "00000111111112220",
             "12221111111112221"},

        /* For Text #2 */
        {" ABC " + ArabicABC + " " + Arabic123 + " 123.",
             "00000111122212220", "00000111122212220", "00000111122212220",
             "12221111122212221"},

        /* For Text #3 */
        {" " + NKoABC + " ABC 123 " + NKo123 + ".",
             "11111222222211111", "11111222222211111", "01110000000001110",
             "11111222222211111"},

        /* For Text #4 */
        {" " + ArabicABC + " ABC 123 " + Arabic123 + ".",
             "11111222222212221", "11111222222212221", "01110000000002220",
             "11111222222212221"},

        /* For Text #5 */
        {" " + HebrewABC + " " + NKo123 + ".",
             "111111111", "111111111", "011111110", "111111111"},

        /* For Text #6 */
        {" " + ArabicABC + " " + Arabic123 + ".",
             "111112221", "111112221", "011112220", "111112221"},

        /* For Text #7 */
        {" " + KharoshthiABC + " " + Kharoshthi123 + ".",
             "111111111111111", "111111111111111", "011111111111110",
             "111111111111111"},

        /* For Text #8 */
        {L + HebrewABC + " " + NKo123 + ".",
             "011111110", "011111110", "011111110", "211111111"},

        /* For Text #9 */
        {R + "ABC " + Osmanya123 + ".",
             "000000000000", "000000000000", "000000000000", "122222222221"},

        /* For Text #10 */
        {"ABC " + PArabicABC + " " + PArabicABC + " 123",
             "000011111111222", "000011111111222", "000011111111222",
             "222111111111222"},

        /* For Text #11 */
        {RLE + "ABC " + HebrewABC + " " + NKo123 + "." + PDF,
             "22221111111110", "22221111111110", "22221111111110",
             "44443333333331"},

        /* For Text #12 */
        {"He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + ".\"",
             "000000000222211111111000", "000000000222211111111000",
             "000000000222211111111000", "222222211444433333333111"},

        /* For Text #13 */
        {LRO + "He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF +
         ".\"" + PDF,
             "22222222224444333333332220", "22222222224444333333332220",
             "22222222224444333333332220", "22222222224444333333332221"},

        /* For Text #14 */
        {LRO + "He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF +
         ".\"",  // PDF missing
             "2222222222444433333333222", "2222222222444433333333222",
             "2222222222444433333333222", "2222222222444433333333222"},

        /* For Text #15 */
        {"Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
         " " + NKo123 + PDF + "\"" + PDF + "'?",
             "0000000000000222222222244443333333322000",
             "0000000000000222222222244443333333322000",
             "0000000000000222222222244443333333322000",
             "2222222222222222222222244443333333322111"},

        /* For Text #16 */
        {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
         HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?" + PDF,
             "111111111111112222222222444433333333221110",
             "111111111111112222222222444433333333221110",
             "111111111111112222222222444433333333221110",
             "333333333333334444444444666655555555443331"},

        /* For Text #17 */
        {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
         HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?",  // PDF missing
             "11111111111111222222222244443333333322111",
             "11111111111111222222222244443333333322111",
             "11111111111111222222222244443333333322111",
             "33333333333333444444444466665555555544333"},

        /* For Text #18 */
        {" ABC (" + ArabicABC + " " + Arabic123 + ") 123.",
             "0000001111222112220", "0000001111222112220",
             "0000001111222112220", "1222111111222112221"},

        /* For Text #19 */
        {" " + HebrewABC + " (ABC 123) " + NKo123 + ".",
             "1111112222222111111", "1111112222222111111",
             "0111000000000001110", "1111112222222111111"},

        /* For Text #20 */
        {" He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF + ".\" ",
             "00000000002222111111110000", "00000000002222111111110000",
             "00000000002222111111110000", "12222222114444333333331111"},

        /* For Text #21 */
        {" Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
         " " + NKo123 + PDF + "\"" + PDF + "'? ",
             "000000000000002222222222444433333333220000",
             "000000000000002222222222444433333333220000",
             "000000000000002222222222444433333333220000",
             "122222222222222222222222444433333333221111"},

        /* For Text #22 */
        {RLE + OsmanyaABC + " " + KharoshthiABC + " " + Kharoshthi123 + "." +
         PDF,
             "22222221111111111111110", "22222221111111111111110",
             "22222221111111111111110", "44444443333333333333331"},
    };

    /* Golden data for baseIsLeftToRight() results */
    private static boolean[][] baseIsLTR4Constructor2 = {
        /* For Text #0 - $4  */
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {false, false, true,  false},
        {false, false, true,  false},

        /* For Text #5 - $9  */
        {false, false, true,  false},
        {false, false, true,  false},
        {false, false, true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},

        /* For Text #10 - $14  */
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},

        /* For Text #15 - $19  */
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {false, false, true,  false},

        /* For Text #20 - $22  */
        {true,  true,  true,  false},
        {true,  true,  true,  false},
        {true,  true,  true,  false},
    };

    /* Golden data for isLeftToRight() & isRightToLeft() results */
    private static boolean[][][] isLTR_isRTL4Constructor2 = {
        /* isLeftToRight() results   &   isRightToLeft() results   */
        /* For Text #0 - $4  */
        {{true,  true,  true,  false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},

        /* For Text #5 - $9  */
        {{false, false, false, false}, {true,  true,  false, true }},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {true,  true,  false, true }},
        {{false, false, false, false}, {false, false, false, false}},
        {{true,  true,  true,  false}, {false, false, false, false}},

        /* For Text #10 - $14  */
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},

        /* For Text #15 - $19  */
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},

        /* For Text #20 - $22  */
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
        {{false, false, false, false}, {false, false, false, false}},
    };

    /* Golden data for requiresBidi() results */
    private static boolean[] requiresBidi4Constructor2 = {
        /* For Text #0 - $9  */
        false, true,  true,  true,  true,
        true,  true,  true,  true,  false,

        /* For Text #10 - $19  */
        true,  true,  true,  true,  true,
        true,  true,  true,  true,  true,

        /* For Text #20 - $22  */
        true,  true,  true,
    };

    /* --------------------------------------------------------------------- */

    /*
     * Test data for Bidi(char[], ...) constructor and methods
     */

    /* Enbeddings */
    private static byte[][][] emb4Constructor3 = {
        /* Embeddings for paragraphs which don't include surrogate pairs. */
        {{0, 0, 0, 0, 0,  1,  1,  1,  1,  1,  1,  1, 0, 0, 0, 0, 0, 0},
         {0, 0, 0, 0, 0,  2,  2,  2,  2,  2,  2,  2, 0, 0, 0, 0, 0, 0},
         {0, 0, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, 0, 0, 0, 0, 0, 0},
         {0, 0, 0, 0, 0, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0}},

        /* Embeddings for paragraphs which include surrogate pairs. */
        {{ 0,  0,  0,  0,  0,  0,  0,  0,
           1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
           0,  0,  0,  0,  0,  0,  0,  0,  0},
         { 0,  0,  0,  0,  0,  0,  0,  0,
           2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
           0,  0,  0,  0,  0,  0,  0,  0,  0},
         { 0,  0,  0,  0,  0,  0,  0,  0,
          -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
           0,  0,  0,  0,  0,  0,  0,  0,  0},
         { 0,  0,  0,  0,  0,  0,  0,  0,
          -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
           0,  0,  0,  0,  0,  0,  0,  0,  0}},
    };

    /* Text for Bidi processing and its levels */
    private static String[][] data4Constructor3 = {
        /* For Text #0 */
        {"abc <ABC XYZ> xyz.",
             /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
             "000002222222000000", "000000000000000000",
             "000003333333000000", "000000000000000000",
             /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
             "222222222222222221", "222222222222222221",
             "222113333333112221", "222224444444222221",
             /* DIRECTION_LEFT_TO_RIGHT */
             "000002222222000000", "000000000000000000",
             "000003333333000000", "000000000000000000",
             /* DIRECTION_RIGHT_TO_LEFT */
             "222222222222222221", "222222222222222221",
             "222113333333112221", "222224444444222221"},

        /* For Text #1 */
        {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
             /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
             "000001111111000000", "000003333333000000",
             "000003333333000000", "000000000000000000",
             /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
             "222111111111112221", "222223333333222221",
             "222113333333112221", "222224444444222221",
             /* DIRECTION_LEFT_TO_RIGHT */
             "000001111111000000", "000003333333000000",
             "000003333333000000", "000000000000000000",
             /* DIRECTION_RIGHT_TO_LEFT */
             "222111111111112221", "222223333333222221",
             "222113333333112221", "222224444444222221"},

        /* For Text #2 */
        {NKoABC + " <ABC XYZ> " + NKo123 + ".",
             /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
             "111112222222111111", "111112222222111111",
             "111111111111111111", "111114444444111111",
             /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
             "111112222222111111", "111112222222111111",
             "111111111111111111", "111114444444111111",
             /* DIRECTION_LEFT_TO_RIGHT */
             "111112222222111110", "111002222222001110",
             "111113333333111110", "111004444444001110",
             /* DIRECTION_RIGHT_TO_LEFT */
             "111112222222111111", "111112222222111111",
             "111111111111111111", "111114444444111111"},

        /* For Text #3 */
        {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
             /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
             "111111111222111111", "111113333444111111",
             "111111111111111111", "111114444444111111",
             /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
             "111111111222111111", "111113333444111111",
             "111111111111111111", "111114444444111111",
             /* DIRECTION_LEFT_TO_RIGHT */
             "111111111222111110", "111003333444001110",
             "111113333333111110", "111004444444001110",
             /* DIRECTION_RIGHT_TO_LEFT */
             "111111111222111111", "111113333444111111",
             "111111111111111111", "111114444444111111"},

        /* For Text #4 */
        {"abc <123 456> xyz.",
             /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
             "000002221222000000", "000000000000000000",
             "000003333333000000", "000000000000000000",
             /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
             "222222222222222221", "222222222222222221",
             "222113333333112221", "222224444444222221",
             /* DIRECTION_LEFT_TO_RIGHT */
             "000002221222000000", "000000000000000000",
             "000003333333000000", "000000000000000000",
             /* DIRECTION_RIGHT_TO_LEFT */
             "222222222222222221", "222222222222222221",
             "222113333333112221", "222224444444222221"},

        /* For Text #5 */
        {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
         Osmanya123 + ".",
             /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
             "000000001111111111111000000000", "000000003333333333333000000000",
             "000000003333333333333000000000", "000000000000000000000000000000",
             /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
             "222222111111111111111112222221", "222222223333333333333222222221",
             "222222113333333333333112222221", "222222224444444444444222222221",
             /* DIRECTION_LEFT_TO_RIGHT */
             "000000001111111111111000000000", "000000003333333333333000000000",
             "000000003333333333333000000000", "000000000000000000000000000000",
             /* DIRECTION_RIGHT_TO_LEFT */
             "222222111111111111111112222221", "222222223333333333333222222221",
             "222222113333333333333112222221", "222222224444444444444222222221"},

        /* For Text #6 */
        {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
         Kharoshthi123 + ".",
             /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
             "111111112222222222222111111111", "111111112222222222222111111111",
             "111111111111111111111111111111", "111111114444444444444111111111",
             /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
             "111111112222222222222111111111", "111111112222222222222111111111",
             "111111111111111111111111111111", "111111114444444444444111111111",
             /* DIRECTION_LEFT_TO_RIGHT */
             "111111112222222222222111111110", "111111002222222222222001111110",
             "111111113333333333333111111110", "111111004444444444444001111110",
             /* DIRECTION_RIGHT_TO_LEFT */
             "111111112222222222222111111111", "111111112222222222222111111111",
             "111111111111111111111111111111", "111111114444444444444111111111"},
    };

    /* Golden data for baseIsLeftToRight() results */
    private static boolean[][] baseIsLTR4Constructor3 = {
        /* For Text #0 */
        {true,  true,  true,  true,    // DIRECTION_DEFAULT_LEFT_TO_RIGHT
         true,  true,  true,  true,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
         true,  true,  true,  true,    // DIRECTION_LEFT_TO_RIGHT
         false, false, false, false},  // DIRECTION_RIGHT_TO_LEFT

        /* For Text #1 */
        {true,  true,  true,  true,
         true,  true,  true,  true,
         true,  true,  true,  true,
         false, false, false, false},

        /* For Text #2 */
        {false, false, false, false,
         false, false, false, false,
         true,  true,  true,  true,
         false, false, false, false},

        /* For Text #3 */
        {false, false, false, false,
         false, false, false, false,
         true,  true,  true,  true,
         false, false, false, false},

        /* For Text #4 */
        {true,  true,  true,  true,
         true,  true,  true,  true,
         true,  true,  true,  true,
         false, false, false, false},

        /* For Text #5 */
        {true,  true,  true,  true,
         true,  true,  true,  true,
         true,  true,  true,  true,
         false, false, false, false},

        /* For Text #6 */
        {false, false, false, false,
         false, false, false, false,
         true,  true,  true,  true,
         false, false, false, false},
    };

    /* Golden data for isLeftToRight() & isRightToLeft() results */
    private static boolean[][][] isLTR_isRTL4Constructor3 = {
        /* For Text #0 */
         /* isLeftToRight() results */
        {{false, true,  false, true,     // DIRECTION_DEFAULT_LEFT_TO_RIGHT
          false, false, false, false,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
          false, true,  false, true,     // DIRECTION_LEFT_TO_RIGHT
          false, false, false, false},   // DIRECTION_RIGHT_TO_LEFT
         /* isRightToLeft() results   */
         {false, false, false, false,    // DIRECTION_DEFAULT_LEFT_TO_RIGHT
          false, false, false, false,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
          false, false, false, false,    // DIRECTION_LEFT_TO_RIGHT
          false, false, false, false}},  // DIRECTION_RIGHT_TO_LEFTT

        /* For Text #1 */
         /* isLeftToRight() results */
        {{false, false, false, true,
          false, false, false, false,
          false, false, false, true,
          false, false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false,
          false, false, false, false,
          false, false, false, false,
          false, false, false, false}},

        /* For Text #2 */
         /* isLeftToRight() results */
        {{false, false, false, false,
          false, false, false, false,
          false, false, false, false,
          false, false, false, false},
         /* isRightToLeft() results   */
         {false, false, true,  false,
          false, false, true,  false,
          false, false, false, false,
          false, false, true,  false}},

        /* For Text #3 */
         /* isLeftToRight() results */
        {{false, false, false, false,
          false, false, false, false,
          false, false, false, false,
          false, false, false, false},
         /* isRightToLeft() results   */
         {false, false, true,  false,
          false, false, true,  false,
          false, false, false, false,
          false, false, true,  false}},

        /* For Text #4 */
         /* isLeftToRight() results */
        {{false, true,  false, true,
          false, false, false, false,
          false, true,  false, true,
          false, false, false, false },
         /* isRightToLeft() results   */
         {false, false, false, false,
          false, false, false, false,
          false, false, false, false,
          false, false, false, false}},

        /* For Text #5 */
         /* isLeftToRight() results */
        {{false, false, false, true,
          false, false, false, false,
          false, false, false, true,
          false, false, false, false},
         /* isRightToLeft() results   */
         {false, false, false, false,
          false, false, false, false,
          false, false, false, false,
          false, false, false, false}},

        /* For Text #6 */
         /* isLeftToRight() results */
        {{false, false, false, false,
          false, false, false, false,
          false, false, false, false,
          false, false, false, false},
         /* isRightToLeft() results   */
         {false, false, true,  false,
          false, false, true,  false,
          false, false, false, false,
          false, false, true,  false}},
    };

    /* --------------------------------------------------------------------- */

    /*
     * Test data for reorderVisually() methods
     */

    private static Object[][][] data4reorderVisually = {
        {{"ABC", " ", "abc", " ", ArabicABC, "."},   // Original text
         {"000000001110"},                           // levels
         {"ABC", " ", "abc", " ", ArabicABC, "."}},  // Reordered text

        {{"ABC", " ", HebrewABC, " ", NKoABC, "."},
         {"222111111111"},
         {".", NKoABC, " ", HebrewABC, " ", "ABC"}},

        {{OsmanyaABC, " ", HebrewABC, " ", KharoshthiABC, "."},
         {"222222111111111111"},
         {".", KharoshthiABC, " ", HebrewABC, " ", OsmanyaABC,}},

        {{"ABC", " ", Osmanya123, " ", "\"", OsmanyaABC, " ", Kharoshthi123,
          " ", KharoshthiABC, ".", "\""},
         {"0000000000002222221111111111111100"},
         {"ABC", " ", Osmanya123, " ", "\"", KharoshthiABC, " ", Kharoshthi123,
          " ", OsmanyaABC, ".", "\""}},
    };

}

Other Java examples (source code examples)

Here is a short list of links related to this Java BidiConformance.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.