private static void convertLineBreakProperties()

in fop-core/src/main/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java [86:482]


    private static void convertLineBreakProperties(
        String lineBreakFileName,
        String propertyValueFileName,
        String breakPairFileName,
        String outFileName)
        throws Exception {

        readLineBreakProperties(lineBreakFileName, propertyValueFileName);
        // read break pair table
        int lineBreakPropertyValueCount = lineBreakPropertyValues.size();
        int tableSize = lineBreakPropertyValueCount - NOT_IN_PAIR_TABLE.length;
        Map notInPairTableMap = new HashMap(NOT_IN_PAIR_TABLE.length);
        for (int i = 0; i < NOT_IN_PAIR_TABLE.length; i++) {
            Object v = lineBreakPropertyValues.get(NOT_IN_PAIR_TABLE[i]);
            if (v == null) {
                throw new Exception("'not in pair table' property not found: " + NOT_IN_PAIR_TABLE[i]);
            }
            notInPairTableMap.put(NOT_IN_PAIR_TABLE[i], v);
        }
        byte[][] pairTable = new byte[tableSize][];
        byte[] columnHeader = new byte[tableSize];
        byte[] rowHeader = new byte[tableSize];
        byte[] columnMap = new byte[lineBreakPropertyValueCount + 1];
        Arrays.fill(columnMap, (byte)255);
        byte[] rowMap = new byte[lineBreakPropertyValueCount + 1];
        Arrays.fill(rowMap, (byte)255);
        BufferedReader b = new BufferedReader(new FileReader(breakPairFileName));
        String line = b.readLine();
        int lineNumber = 1;
        String[] lineTokens;
        String name;
        // read header
        if (line != null) {
            lineTokens = line.split("\\s+");
            byte columnNumber = 0;

            for (int i = 0; i < lineTokens.length; ++i) {
                name = lineTokens[i];
                if (name.length() > 0) {
                    if (columnNumber >= columnHeader.length) {
                        throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected column header " + name);
                    }
                    if (notInPairTableMap.get(name) != null) {
                        throw new Exception(breakPairFileName + ':' + lineNumber + ": invalid column header " + name);
                    }
                    Byte v = (Byte)lineBreakPropertyValues.get(name);
                    if (v != null) {
                        byte vv = v.byteValue();
                        columnHeader[columnNumber] = vv;
                        columnMap[vv] = columnNumber;
                    } else {
                        throw new Exception(breakPairFileName + ':' + lineNumber + ": unknown column header " + name);
                    }
                    columnNumber++;
                }
            }
            if (columnNumber < columnHeader.length) {
                StringBuffer missing = new StringBuffer();
                for (int j = 0; j < lineBreakPropertyShortNames.size(); j++) {
                    boolean found = false;
                    for (int k = 0; k < columnNumber; k++) {
                        if (columnHeader[k] == j + 1) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        if (missing.length() > 0) {
                            missing.append(", ");
                        }
                        missing.append((String)lineBreakPropertyShortNames.get(j));
                    }
                }
                throw new Exception(
                    breakPairFileName + ':' + lineNumber + ": missing column for properties: " + missing.toString());
            }
        } else {
            throw new Exception(breakPairFileName + ':' + lineNumber + ": can't read table header");
        }
        line = b.readLine().trim();
        lineNumber++;
        byte rowNumber = 0;
        while (line != null && line.length() > 0) {
            if (rowNumber >= rowHeader.length) {
                throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected row " + line);
            }
            pairTable[rowNumber] = new byte[tableSize];
            lineTokens = line.split("\\s+");
            if (lineTokens.length > 0) {
                name = lineTokens[0];
                if (notInPairTableMap.get(name) != null) {
                    throw new Exception(breakPairFileName + ':' + lineNumber + ": invalid row header " + name);
                }
                Byte v = (Byte)lineBreakPropertyValues.get(name);
                if (v != null) {
                    byte vv = v.byteValue();
                    rowHeader[rowNumber] = vv;
                    rowMap[vv] = rowNumber;
                } else {
                    throw new Exception(breakPairFileName + ':' + lineNumber + ": unknown row header " + name);
                }
            } else {
                throw new Exception(breakPairFileName + ':' + lineNumber + ": can't read row header");
            }
            int columnNumber = 0;
            String token;
            for (int i = 1; i < lineTokens.length; ++i) {
                token = lineTokens[i];
                if (token.length() == 1) {
                    byte tokenBreakClass = (byte)BREAK_CLASS_TOKENS.indexOf(token.charAt(0));
                    if (tokenBreakClass >= 0) {
                        pairTable[rowNumber][columnNumber] = tokenBreakClass;
                    } else {
                        throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected token: " + token);
                    }
                } else {
                    throw new Exception(breakPairFileName + ':' + lineNumber + ": token too long: " + token);
                }
                columnNumber++;
            }
            line = b.readLine().trim();
            lineNumber++;
            rowNumber++;
        }
        if (rowNumber < rowHeader.length) {
            StringBuffer missing = new StringBuffer();
            for (int j = 0; j < lineBreakPropertyShortNames.size(); j++) {
                boolean found = false;
                for (int k = 0; k < rowNumber; k++) {
                    if (rowHeader[k] == j + 1) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    if (missing.length() > 0) {
                        missing.append(", ");
                    }
                    missing.append((String)lineBreakPropertyShortNames.get(j));
                }
            }
            throw new Exception(
                breakPairFileName + ':' + lineNumber + ": missing row for properties: " + missing.toString());
        }

        // generate class
        int rowsize = 512;
        int blocksize = lineBreakProperties.length / rowsize;
        byte[][] row = new byte[rowsize][];
        int idx = 0;
        StringBuffer doStaticLinkCode = new StringBuffer();
        PrintWriter out = new PrintWriter(new FileWriter(outFileName));
        License.writeJavaLicenseId(out);
        out.println();
        out.println("package org.apache.fop.text.linebreak;");
        out.println();
        out.println("/*");
        out.println(" * !!! THIS IS A GENERATED FILE !!!");
        out.println(" * If updates to the source are needed, then:");
        out.println(" * - apply the necessary modifications to");
        out.println(" *   'src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java'");
        out.println(" * - run 'ant codegen-unicode', which will generate a new LineBreakUtils.java");
        out.println(" *   in 'src/java/org/apache/fop/text/linebreak'");
        out.println(" * - commit BOTH changed files");
        out.println(" */");
        out.println();
        out.println("// CSOFF: WhitespaceAfterCheck");
        out.println("// CSOFF: LineLengthCheck");
        out.println();
        out.println("/** Line breaking utilities. */");
        out.println("public final class LineBreakUtils {");
        out.println();
        out.println("    private LineBreakUtils() {");
        out.println("    }");
        out.println();
        out.println("    /** Break class constant */");
        out.println("    public static final byte DIRECT_BREAK = " + DIRECT_BREAK + ';');
        out.println("    /** Break class constant */");
        out.println("    public static final byte INDIRECT_BREAK = " + INDIRECT_BREAK + ';');
        out.println("    /** Break class constant */");
        out.println("    public static final byte COMBINING_INDIRECT_BREAK = " + COMBINING_INDIRECT_BREAK + ';');
        out.println("    /** Break class constant */");
        out.println("    public static final byte COMBINING_PROHIBITED_BREAK = " + COMBINING_PROHIBITED_BREAK + ';');
        out.println("    /** Break class constant */");
        out.println("    public static final byte PROHIBITED_BREAK = " + PROHIBITED_BREAK + ';');
        out.println("    /** Break class constant */");
        out.println("    public static final byte EXPLICIT_BREAK = " + EXPLICIT_BREAK + ';');
        out.println();
        out.println("    private static final byte[][] PAIR_TABLE = {");
        boolean printComma = false;
        for (int i = 1; i <= lineBreakPropertyValueCount; i++) {
            if (printComma) {
                out.println(",");
            } else {
                printComma = true;
            }
            out.print("        {");
            boolean localPrintComma = false;
            for (int j = 1; j <= lineBreakPropertyValueCount; j++) {
                if (localPrintComma) {
                    out.print(", ");
                } else {
                    localPrintComma = true;
                }
                if (columnMap[j] != -1 && rowMap[i] != -1) {
                    out.print(pairTable[rowMap[i]][columnMap[j]]);
                } else {
                    out.print('0');
                }
            }
            out.print('}');
        }
        out.println("};");
        out.println();
        out.println("    private static byte[][] lineBreakProperties = new byte[" + rowsize + "][];");
        out.println();
        out.println("    private static void init0() {");
        int rowsPrinted = 0;
        int initSections = 0;
        for (int i = 0; i < rowsize; i++) {
            boolean found = false;
            for (int j = 0; j < i; j++) {
                if (row[j] != null) {
                    boolean matched = true;
                    for (int k = 0; k < blocksize; k++) {
                        if (row[j][k] != lineBreakProperties[idx + k]) {
                            matched = false;
                            break;
                        }
                    }
                    if (matched) {
                        found = true;
                        doStaticLinkCode.append("        lineBreakProperties[");
                        doStaticLinkCode.append(i);
                        doStaticLinkCode.append("] = lineBreakProperties[");
                        doStaticLinkCode.append(j);
                        doStaticLinkCode.append("];\n");
                        break;
                    }
                }
            }
            if (!found) {
                if (rowsPrinted >= 64) {
                    out.println("    }");
                    out.println();
                    initSections++;
                    out.println("    private static void init" + initSections + "() {");
                    rowsPrinted = 0;
                }
                row[i] = new byte[blocksize];
                boolean printLocalComma = false;
                out.print("        lineBreakProperties[" + i + "] = new byte[] { ");
                for (int k = 0; k < blocksize; k++) {
                    row[i][k] = lineBreakProperties[idx + k];
                    if (printLocalComma) {
                        out.print(", ");
                    } else {
                        printLocalComma = true;
                    }
                    out.print(row[i][k]);
                }
                out.println("};");
                rowsPrinted++;
            }
            idx += blocksize;
        }
        out.println("    }");
        out.println();
        out.println("    static {");
        for (int i = 0; i <= initSections; i++) {
            out.println("        init" + i + "();");
        }
        out.print(doStaticLinkCode);
        out.println("    }");
        out.println();
        for (int i = 0; i < lineBreakPropertyShortNames.size(); i++) {
            String shortName = (String)lineBreakPropertyShortNames.get(i);
            out.println("    /** Linebreak property constant */");
            out.print("    public static final byte LINE_BREAK_PROPERTY_");
            out.print(shortName);
            out.print(" = ");
            out.print(i + 1);
            out.println(';');
        }
        out.println();
        final String shortNamePrefix = "    private static String[] lineBreakPropertyShortNames = {";
        out.print(shortNamePrefix);
        int lineLength = shortNamePrefix.length();
        printComma = false;
        for (int i = 0; i < lineBreakPropertyShortNames.size(); i++) {
            name = (String)lineBreakPropertyShortNames.get(i);
            if (printComma) {
                if (lineLength <= MAX_LINE_LENGTH - 2) {
                    out.print(", ");
                } else {
                    out.print(",");
                }
                // count the space anyway to force a linebreak if the comma causes lineLength == MAX_LINE_LENGTH
                lineLength += 2;
            } else {
                printComma = true;
            }
            if (lineLength > MAX_LINE_LENGTH) {
                out.println();
                out.print("        ");
                lineLength = 8;
            }
            out.print('"');
            out.print(name);
            out.print('"');
            lineLength += (2 + name.length());
        }
        out.println("};");
        out.println();
        final String longNamePrefix = "    private static String[] lineBreakPropertyLongNames = {";
        out.print(longNamePrefix);
        lineLength = longNamePrefix.length();
        printComma = false;
        for (int i = 0; i < lineBreakPropertyLongNames.size(); i++) {
            name = (String)lineBreakPropertyLongNames.get(i);
            if (printComma) {
                out.print(',');
                lineLength++;
            } else {
                printComma = true;
            }
            if (lineLength > MAX_LINE_LENGTH) {
                out.println();
                out.print("        ");
                lineLength = 8;
            }
            out.print('"');
            out.print(name);
            out.print('"');
            lineLength += (2 + name.length());
        }
        out.println("};");
        out.println();
        out.println("    /**");
        out.println("     * Return the short name for the linebreak property corresponding");
        out.println("     * to the given symbolic constant.");
        out.println("     *");
        out.println("     * @param i the numeric value of the linebreak property");
        out.println("     * @return the short name of the linebreak property");
        out.println("     */");
        out.println("    public static String getLineBreakPropertyShortName(byte i) {");
        out.println("        if (i > 0 && i <= lineBreakPropertyShortNames.length) {");
        out.println("            return lineBreakPropertyShortNames[i - 1];");
        out.println("        } else {");
        out.println("            return null;");
        out.println("        }");
        out.println("    }");
        out.println();
        out.println("    /**");
        out.println("     * Return the long name for the linebreak property corresponding");
        out.println("     * to the given symbolic constant.");
        out.println("     *");
        out.println("     * @param i the numeric value of the linebreak property");
        out.println("     * @return the long name of the linebreak property");
        out.println("     */");
        out.println("    public static String getLineBreakPropertyLongName(byte i) {");
        out.println("        if (i > 0 && i <= lineBreakPropertyLongNames.length) {");
        out.println("            return lineBreakPropertyLongNames[i - 1];");
        out.println("        } else {");
        out.println("            return null;");
        out.println("        }");
        out.println("    }");
        out.println();
        out.println("    /**");
        out.println("     * Return the linebreak property constant for the given <code>char</code>");
        out.println("     *");
        out.println("     * @param c the <code>char</code> whose linebreak property to return");
        out.println("     * @return the constant representing the linebreak property");
        out.println("     */");
        out.println("    public static byte getLineBreakProperty(char c) {");
        out.println("        return lineBreakProperties[c / " + blocksize + "][c % " + blocksize + "];");
        out.println("    }");
        out.println();
        out.println("    /**");
        out.println("     * Return the break class constant for the given pair of linebreak");
        out.println("     * property constants.");
        out.println("     *");
        out.println("     * @param lineBreakPropertyBefore the linebreak property for the first character");
        out.println("     *        in a two-character sequence");
        out.println("     * @param lineBreakPropertyAfter the linebreak property for the second character");
        out.println("     *        in a two-character sequence");
        out.println("     * @return the constant representing the break class");
        out.println("     */");
        out.println(
            "    public static byte getLineBreakPairProperty(int lineBreakPropertyBefore, int lineBreakPropertyAfter) {");
        out.println("        return PAIR_TABLE[lineBreakPropertyBefore - 1][lineBreakPropertyAfter - 1];");
        out.println("    }");
        out.println();
        out.println("}");
        out.flush();
        out.close();
    }