]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Moved the class UnicodeClasses to src/codegen/unicode, so that it is
authorSimon Pepping <spepping@apache.org>
Thu, 3 Sep 2009 11:36:02 +0000 (11:36 +0000)
committerSimon Pepping <spepping@apache.org>
Thu, 3 Sep 2009 11:36:02 +0000 (11:36 +0000)
only built when the classes.xml file is regenerated. Modified the
build file accordingly. Restored Java 5 features in
UnicodeClasses. Created a License utility class. Added a license
statement and a generated file statement to classes.xml. Made
GenerateLineBreakUtils.java use the License class, and made it avoid
trailing spaces in the generated file.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@810896 13f79535-47bb-0310-9956-ffa450edef68

build.xml
src/codegen/unicode/java/org/apache/fop/hyphenation/UnicodeClasses.java [new file with mode: 0644]
src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java
src/codegen/unicode/java/org/apache/fop/util/License.java [new file with mode: 0644]
src/java/org/apache/fop/hyphenation/UnicodeClasses.java [deleted file]
src/java/org/apache/fop/hyphenation/classes.xml

index cf1900461dcd7e6ef83fefb71093336f170eade3..467e291921794dbe6e15accef7b10bbe495ef163 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -436,8 +436,11 @@ list of possible build targets.
   <!-- (src/java/org/apache/fop/hyphenation/classes.xml). -->
   <!-- =================================================================== -->
   <target name="codegen-hyphenation-classes">
-       <java classname="org.apache.fop.hyphenation.UnicodeClasses" resultproperty="classes.result" classpath="${build.classes.dir}">
-         <arg value="${unidata.dir}"/>
+    <javac destdir="${build.codegen-classes.dir}" fork="${javac.fork}" debug="${javac.debug}" deprecation="${javac.deprecation}" optimize="${javac.optimize}" source="${javac.source}" target="${javac.target}">
+      <src path="${src.codegen.dir}/unicode/java"/>
+    </javac>
+       <java classname="org.apache.fop.hyphenation.UnicodeClasses" resultproperty="classes.result" classpath="${build.codegen-classes.dir}">
+      <arg value="${src.dir}/java/org/apache/fop/hyphenation/classes.xml"/>
        </java>
        <condition property="classes.result.message" value="Generation of classes successful">
          <not>
diff --git a/src/codegen/unicode/java/org/apache/fop/hyphenation/UnicodeClasses.java b/src/codegen/unicode/java/org/apache/fop/hyphenation/UnicodeClasses.java
new file mode 100644 (file)
index 0000000..4b3b9f7
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.hyphenation;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.fop.util.License;
+
+/**
+ * Create the default classes file classes.xml,
+ * for use in building hyphenation patterns
+ * from pattern files which do not contain their own classes.
+ * The class contains three methods to do that.
+ * The method fromJava gets its infirmation from Java's compiled-in Unicode Character Database,
+ * the method fromUCD gets its information from the UCD files,
+ * the method fromTeX gets its information from the file unicode-letters-XeTeX.tex,
+ * which is the basis of XeTeX's unicode support.
+ * In the build file only the method from UCD is used;
+ * the other two methods are there for demonstration.
+ * The methods fromJava and fromTeX are commented out because they are not Java 1.4 compliant.
+ */
+public final class UnicodeClasses {
+    
+    public static String UNICODE_DIR = "http://www.unicode.org/Public/UNIDATA/";
+
+    /**
+     * Disallow constructor for this utility class
+     */
+    private UnicodeClasses() { }
+
+    /**
+     * Write a comment that this is a generated file,
+     * and instructions on how to generate it
+     * @param w the writer which writes the comment
+     * @throws IOException if the write operation fails
+     */
+    public static void writeGenerated(Writer w) throws IOException {
+        w.write("<!-- !!! THIS IS A GENERATED FILE !!!             -->\n");
+        w.write("<!-- If updates are needed, then:                 -->\n");
+        w.write("<!-- * run 'ant codegen-hyphenation-classes',     -->\n");
+        w.write("<!--   which will generate a new file classes.xml -->\n");
+        w.write("<!--   in 'src/java/org/apache/fop/hyphenation'   -->\n");
+        w.write("<!-- * commit the changed file                    -->\n");
+    }
+    
+    /**
+     * Generate classes.xml from Java's compiled-in Unicode Character Database
+     * @param hexcode whether to prefix each class with the hexcode (only for debugging purposes)
+     * @param outfilePath output file
+     * @throws IOException
+     */
+    public static void fromJava(boolean hexcode, String outfilePath) throws IOException {
+        File f = new File(outfilePath);
+        if (f.exists()) {
+            f.delete();
+        }
+        f.createNewFile();
+        FileOutputStream fw = new FileOutputStream(f);
+        OutputStreamWriter ow = new OutputStreamWriter(fw, "utf-8");
+        int maxChar;
+        maxChar = Character.MAX_VALUE;
+
+        ow.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+        License.writeXMLLicenseId(ow);
+        ow.write("\n");
+        writeGenerated(ow);
+        ow.write("\n");
+        ow.write("<classes>\n");
+        // loop over the first Unicode plane
+        for (int code = Character.MIN_VALUE; code <= maxChar; ++code) {
+            
+            // skip surrogate area
+            if (code == Character.MIN_SURROGATE) {
+                code = Character.MAX_SURROGATE;
+                continue;
+            }
+
+            // we are only interested in LC, UC and TC letters which are their own LC,
+            // and in 'other letters'
+            if (!(((Character.isLowerCase(code) || Character.isUpperCase(code)
+                    || Character.isTitleCase(code))
+                    && code == Character.toLowerCase(code))
+                    || Character.getType(code) == Character.OTHER_LETTER)) {
+                continue;
+            }
+            
+            // skip a number of blocks
+            Character.UnicodeBlock ubi = Character.UnicodeBlock.of(code);
+            if (ubi.equals(Character.UnicodeBlock.SUPERSCRIPTS_AND_SUBSCRIPTS)
+                    || ubi.equals(Character.UnicodeBlock.LETTERLIKE_SYMBOLS)
+                    || ubi.equals(Character.UnicodeBlock.ALPHABETIC_PRESENTATION_FORMS)
+                    || ubi.equals(Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS)
+                    || ubi.equals(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)
+                    || ubi.equals(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A)
+                    || ubi.equals(Character.UnicodeBlock.HANGUL_SYLLABLES)) {
+                continue;
+            }
+
+            int uppercode = Character.toUpperCase(code);
+            int titlecode = Character.toTitleCase(code);
+            StringBuilder s = new StringBuilder();
+            if (hexcode) {
+                s.append("0x" + Integer.toHexString(code) + " ");
+            }
+            s.append(Character.toChars(code));
+            if (uppercode != code) {
+                s.append(Character.toChars(uppercode));
+            }
+            if (titlecode != code && titlecode != uppercode) {
+                s.append(Character.toChars(titlecode));
+            }
+            ow.write(s.toString() + "\n");
+        }
+        ow.write("</classes>\n");
+        ow.flush();
+        ow.close();
+    }
+    
+    
+    /**
+     * The column numbers in the UCD file
+     */
+    public static final int UNICODE = 0, GENERAL_CATEGORY = 2, SIMPLE_UPPERCASE_MAPPING = 12,
+    SIMPLE_LOWERCASE_MAPPING = 13, SIMPLE_TITLECASE_MAPPING = 14, NUM_FIELDS = 15;
+    
+    /**
+     * Generate classes.xml from Unicode Character Database files
+     * @param hexcode whether to prefix each class with the hexcode (only for debugging purposes)
+     * @param unidataPath path to the directory with UCD files  
+     * @param outfilePath output file
+     * @throws IOException if the input files are not found
+     * @throws URISyntaxException 
+     * @throws FOPException 
+     */
+    public static void fromUCD(boolean hexcode, String unidataPath, String outfilePath)
+    throws IOException, URISyntaxException {
+        URI unidata;
+        if (unidataPath.endsWith("/")) {
+            unidata = new URI(unidataPath);
+        } else {
+            unidata = new URI(unidataPath + "/");
+        }
+        String scheme = unidata.getScheme();
+        if (scheme == null || !(scheme.equals("file") || scheme.equals("http"))) {
+            throw new FileNotFoundException
+            ("URI with file or http scheme required for UNIDATA input directory");
+        }
+        
+        File f = new File(outfilePath);
+        if (f.exists()) {
+            f.delete();
+        }
+        f.createNewFile();
+        FileOutputStream fw = new FileOutputStream(f);
+        OutputStreamWriter ow = new OutputStreamWriter(fw, "utf-8");
+        
+        URI inuri = unidata.resolve("Blocks.txt");
+        InputStream inis = null;
+        if (scheme.equals("file")) {
+            File in = new File(inuri);
+            inis = new FileInputStream(in);
+        } else if (scheme.equals("http")) {
+            inis = inuri.toURL().openStream();
+        }
+        InputStreamReader insr = new InputStreamReader(inis, "utf-8");
+        BufferedReader inbr = new BufferedReader(insr);
+        Map blocks = new HashMap();
+        for (String line = inbr.readLine(); line != null; line = inbr.readLine()) {
+            if (line.startsWith("#") || line.matches("^\\s*$")) {
+                continue;
+            }
+            String[] parts = line.split(";");
+            String block = parts[1].trim();
+            String[] indices = parts[0].split("\\.\\.");
+            int[] ind = {Integer.parseInt(indices[0], 16), Integer.parseInt(indices[1], 16)};
+            blocks.put(block, ind);
+        }
+        inbr.close();
+
+        inuri = unidata.resolve("UnicodeData.txt");
+        if (scheme.equals("file")) {
+            File in = new File(inuri);
+            inis = new FileInputStream(in);
+        } else if (scheme.equals("http")) {
+            inis = inuri.toURL().openStream();
+        }
+        insr = new InputStreamReader(inis, "utf-8");
+        inbr = new BufferedReader(insr);
+        int maxChar;
+        maxChar = Character.MAX_VALUE;
+
+        ow.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+        License.writeXMLLicenseId(ow);
+        ow.write("\n");
+        writeGenerated(ow);
+        ow.write("\n");
+        ow.write("<classes>\n");
+        for (String line = inbr.readLine(); line != null; line = inbr.readLine()) {
+            String[] fields = line.split(";", NUM_FIELDS);
+            int code = Integer.parseInt(fields[UNICODE], 16);
+            if (code > maxChar) {
+                break;
+            }
+            if (((fields[GENERAL_CATEGORY].equals("Ll") || fields[GENERAL_CATEGORY].equals("Lu")
+                            || fields[GENERAL_CATEGORY].equals("Lt"))
+                        && ("".equals(fields[SIMPLE_LOWERCASE_MAPPING])
+                                || fields[UNICODE].equals(fields[SIMPLE_LOWERCASE_MAPPING])))
+                    || fields[GENERAL_CATEGORY].equals("Lo")) {
+                String[] blockNames = {"Superscripts and Subscripts",
+                                       "Letterlike Symbols",
+                                       "Alphabetic Presentation Forms",
+                                       "Halfwidth and Fullwidth Forms",
+                                       "CJK Unified Ideographs",
+                                       "CJK Unified Ideographs Extension A",
+                                       "Hangul Syllables"};
+                int j;
+                for (j = 0; j < blockNames.length; ++j) {
+                    int[] ind = (int[]) blocks.get(blockNames[j]);
+                    if (code >= ind[0] && code <= ind[1]) {
+                        break;
+                    }
+                }
+                if (j < blockNames.length) {
+                    continue;
+                }
+            
+                int uppercode = -1, titlecode = -1;
+                if (!"".equals(fields[SIMPLE_UPPERCASE_MAPPING])) {
+                    uppercode = Integer.parseInt(fields[SIMPLE_UPPERCASE_MAPPING], 16);
+                }
+                if (!"".equals(fields[SIMPLE_TITLECASE_MAPPING])) {
+                    titlecode = Integer.parseInt(fields[SIMPLE_TITLECASE_MAPPING], 16);
+                }
+                StringBuilder s = new StringBuilder();
+                if (hexcode) {
+                    s.append("0x" + fields[UNICODE].replaceFirst("^0+", "").toLowerCase() + " ");
+                }
+                s.append(Character.toChars(code));
+                if (uppercode != -1 && uppercode != code) {
+                    s.append(Character.toChars(uppercode));
+                }
+                if (titlecode != -1 && titlecode != code && titlecode != uppercode) {
+                    s.append(Character.toChars(titlecode));
+                }
+                ow.write(s.toString() + "\n");
+            }
+        }
+        ow.write("</classes>\n");
+        ow.flush();
+        ow.close();
+        inbr.close();
+    }
+
+    /**
+     * Generate classes.xml from XeTeX's Unicode letters file
+     * @param hexcode whether to prefix each class with the hexcode (only for debugging purposes)
+     * @param lettersPath path to XeTeX's Unicode letters file unicode-letters-XeTeX.tex  
+     * @param outfilePath output file
+     * @throws IOException
+     */
+    public static void fromTeX(boolean hexcode, String lettersPath, String outfilePath)
+      throws IOException {
+        File in = new File(lettersPath);
+
+        File f = new File(outfilePath);
+        if (f.exists()) {
+            f.delete();
+        }
+        f.createNewFile();
+        FileOutputStream fw = new FileOutputStream(f);
+        OutputStreamWriter ow = new OutputStreamWriter(fw, "utf-8");
+
+        FileInputStream inis = new FileInputStream(in);
+        InputStreamReader insr = new InputStreamReader(inis, "utf-8");
+        BufferedReader inbr = new BufferedReader(insr);
+
+        ow.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+        License.writeXMLLicenseId(ow);
+        ow.write("\n");
+        writeGenerated(ow);
+        ow.write("\n");
+        ow.write("<classes>\n");
+        for (String line = inbr.readLine(); line != null; line = inbr.readLine()) {
+            String[] codes = line.split("\\s+");
+            if (!(codes[0].equals("\\L") || codes[0].equals("\\l"))) {
+                continue;
+            }
+            if (codes.length == 3) {
+                ow.write("\"" + line + "\" has two codes");
+                continue;
+            }
+            if (codes[0].equals("\\l") && codes.length != 2) {
+                ow.write("\"" + line + "\" should have one code");
+                continue;
+            }
+            else if (codes[0].equals("\\L") && codes.length != 4) {
+                ow.write("\"" + line + "\" should have three codes");
+                continue;
+            }
+            if (codes[0].equals("\\l") || (codes[0].equals("\\L") && codes[1].equals(codes[3]))) {
+                StringBuilder s = new StringBuilder();
+                if (hexcode) {
+                    s.append("0x" + codes[1].replaceFirst("^0+", "").toLowerCase() + " ");
+                }
+                s.append(Character.toChars(Integer.parseInt(codes[1], 16)));
+                if (codes[0].equals("\\L")) {
+                    s.append(Character.toChars(Integer.parseInt(codes[2], 16)));
+                }
+                ow.write(s.toString() + "\n");
+            }
+        }
+        ow.write("</classes>\n");
+        ow.flush();
+        ow.close();
+        inbr.close();
+    }
+
+    
+    /**
+     * @param args [--hexcode] [--java|--ucd|--tex] outfile [infile]
+     * @throws IOException if the input file cannot be found
+     * @throws URISyntaxException if the input URI is incorrect
+     */
+    public static void main(String[] args) throws IOException, URISyntaxException {
+        String type = "ucd", prefix = "--", infile = null, outfile = null;
+        boolean hexcode = false;
+        int i;
+        for (i = 0; i < args.length && args[i].startsWith(prefix); ++i) {
+            String option = args[i].substring(prefix.length());
+            if (option.equals("java") || option.equals("ucd") || option.equals("tex")) {
+                type = option;
+            } else if (option.equals("hexcode")) {
+                hexcode = true;
+            } else {
+                System.err.println("Unknown option: " + option);
+                System.exit(1);
+            }
+        }
+        if (i < args.length) {
+            outfile = args[i];
+        } else {
+            System.err.println("Output file is required; aborting");
+            System.exit(1);
+        }
+        if (++i < args.length) {
+            infile = args[i];
+        }
+        
+        if (type.equals("java") && infile != null) {
+                System.err.println("Type java does not allow an infile");
+                System.exit(1);
+        } else if (type.equals("ucd") && infile == null) {
+                infile = UNICODE_DIR;
+        } else if (type.equals("tex") && infile == null) {
+                System.err.println("Type tex requires an input file");
+                System.exit(1);
+        }
+        if (type.equals("java")) {
+            fromJava(hexcode, outfile);
+        } else if (type.equals("ucd")) {
+            fromUCD(hexcode, infile, outfile);
+        } else if (type.equals("tex")) {
+            fromTeX(hexcode, infile, outfile);
+        } else {
+            System.err.println("Unknown type: " + type + ", nothing done");
+            System.exit(1);
+        }
+    }
+
+}
index cb02883349e09856b9db77a3a7eb55106aeeb3d0..f96b7484fcc365551df22dfabe42ed6a77115501 100644 (file)
@@ -31,6 +31,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.fop.util.License;
+
 /**
  * <p>Utility for generating a Java class representing line break properties
  * from the Unicode property files.</p>
@@ -226,31 +228,14 @@ public class GenerateLineBreakUtils {
         int idx = 0;
         StringBuffer doStaticLinkCode = new StringBuffer();
         PrintWriter out = new PrintWriter(new FileWriter(outFileName));
-        out.println("/*");
-        out.println(" * Licensed to the Apache Software Foundation (ASF) under one or more");
-        out.println(" * contributor license agreements.  See the NOTICE file distributed with");
-        out.println(" * this work for additional information regarding copyright ownership.");
-        out.println(" * The ASF licenses this file to You under the Apache License, Version 2.0");
-        out.println(" * (the \"License\"); you may not use this file except in compliance with");
-        out.println(" * the License.  You may obtain a copy of the License at");
-        out.println(" * ");
-        out.println(" *      http://www.apache.org/licenses/LICENSE-2.0");
-        out.println(" * ");
-        out.println(" * Unless required by applicable law or agreed to in writing, software");
-        out.println(" * distributed under the License is distributed on an \"AS IS\" BASIS,");
-        out.println(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
-        out.println(" * See the License for the specific language governing permissions and");
-        out.println(" * limitations under the License.");
-        out.println(" */");
-        out.println();
-        out.println("/* $Id$ */");
+        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("/*");
+        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(" * - 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'");
@@ -276,7 +261,7 @@ public class GenerateLineBreakUtils {
         boolean printComma = false;
         for (int i = 1; i <= lineBreakPropertyValueCount; i++) {
             if (printComma) {
-                out.println(", ");
+                out.println(",");
             } else {
                 printComma = true;
             }
@@ -376,8 +361,13 @@ public class GenerateLineBreakUtils {
         for (int i = 0; i < lineBreakPropertyShortNames.size(); i++) {
             name = (String)lineBreakPropertyShortNames.get(i);
             if (printComma) {
-                out.print(", ");
-                lineLength++;
+                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;
             }
@@ -418,7 +408,7 @@ public class GenerateLineBreakUtils {
         out.println("};");
         out.println();
         out.println("    /**");
-        out.println("     * Return the short name for the linebreak property corresponding ");
+        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");
@@ -433,7 +423,7 @@ public class GenerateLineBreakUtils {
         out.println("    }");
         out.println();
         out.println("    /**");
-        out.println("     * Return the long name for the linebreak property corresponding ");
+        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");
@@ -458,7 +448,7 @@ public class GenerateLineBreakUtils {
         out.println("    }");
         out.println();
         out.println("    /**");
-        out.println("     * Return the break class constant for the given pair of linebreak ");
+        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");
diff --git a/src/codegen/unicode/java/org/apache/fop/util/License.java b/src/codegen/unicode/java/org/apache/fop/util/License.java
new file mode 100644 (file)
index 0000000..b6e3db8
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.util;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
+
+/**
+ * Write the Apache license text in various forms
+ */
+public final class License {
+    
+    /**
+     * The Apache license text as a string array
+     */
+    public static final String[] license
+    = {"Licensed to the Apache Software Foundation (ASF) under one or more",
+       "contributor license agreements.  See the NOTICE file distributed with",
+       "this work for additional information regarding copyright ownership.",
+       "The ASF licenses this file to You under the Apache License, Version 2.0",
+       "(the \"License\"); you may not use this file except in compliance with",
+       "the License.  You may obtain a copy of the License at",
+       "",
+       "     http://www.apache.org/licenses/LICENSE-2.0",
+       "",
+       "Unless required by applicable law or agreed to in writing, software",
+       "distributed under the License is distributed on an \"AS IS\" BASIS,",
+       "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
+       "See the License for the specific language governing permissions and",
+       "limitations under the License."
+    };
+
+    /**
+     * The subversion Id keyword line
+     */
+    public static final String id = "$Id$";
+    
+    /**
+     * Calculate the maximum line length in the Apache license text
+     * for use in formatting 
+     */
+    private static int MAX_LENGTH;
+    static {
+        int j = 0;
+        for (int i = 0; i < license.length; ++i) {
+            if (j < license[i].length()) {
+                j = license[i].length();
+            }
+        }
+        MAX_LENGTH = j;
+    }
+
+    /**
+     * Write the Apache license text as commented lines for a Java file
+     * @param w the writer which writes the comment
+     * @throws IOException if the write operation fails
+     */
+    public static void writeJavaLicenseId(Writer w) throws IOException {
+        w.write("/*\n");
+        for (int i = 0; i < license.length; ++i) {
+            if (license[i].equals("")) {
+                w.write(" *\n");
+            } else {
+                w.write(" * " + license[i] + "\n");
+            }
+        }
+        w.write(" */\n");
+        w.write("\n");
+        w.write("/* " + id + " */\n");
+    }
+
+    /**
+     * Write the Apache license text as commented lines for an XML file
+     * @param w the writer which writes the comment
+     * @throws IOException if the write operation fails
+     */
+    public static void writeXMLLicenseId(Writer w) throws IOException {
+        for (int i = 0; i < license.length; ++i) {
+            w.write(String.format("<!-- %-" + MAX_LENGTH + "s -->\n", new Object[] {license[i]}));
+        }
+        w.write("\n");
+        w.write("<!-- " + id + " -->\n");
+    }
+    
+    /**
+     * For testing purposes
+     * @param args optional, --java or --xml
+     * @throws IOException if the write operation fails
+     */
+    public static void main(String[] args) throws IOException {
+        StringWriter w = new StringWriter();
+        if (args.length == 0 || args[0].equals("--java")) {
+            writeJavaLicenseId(w);
+        } else if (args[0].equals("--xml")) {
+            writeXMLLicenseId(w);
+        }
+        System.out.println(w.toString());
+    }
+
+}
diff --git a/src/java/org/apache/fop/hyphenation/UnicodeClasses.java b/src/java/org/apache/fop/hyphenation/UnicodeClasses.java
deleted file mode 100644 (file)
index 328ba8e..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.hyphenation;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Create the default classes file classes.xml,
- * for use in building hyphenation patterns
- * from pattern files which do not contain their own classes.
- * The class contains three methods to do that.
- * The method fromJava gets its infirmation from Java's compiled-in Unicode Character Database,
- * the method fromUCD gets its information from the UCD files,
- * the method fromTeX gets its information from the file unicode-letters-XeTeX.tex,
- * which is the basis of XeTeX's unicode support.
- * In the build file only the method from UCD is used;
- * the other two methods are there for demonstration.
- * The methods fromJava and fromTeX are commented out because they are not Java 1.4 compliant.
- */
-public final class UnicodeClasses {
-    
-    /**
-     * default path relative to the FOP base directory
-     */
-    public static final String CLASSES_XML = "src/java/org/apache/fop/hyphenation/classes.xml";
-    
-    /**
-     * Disallow constructor for this utility class
-     */
-    private UnicodeClasses() { }
-
-    /**
-     * Generate classes.xml from Java's compiled-in Unicode Character Database
-     * @param hexcode whether to prefix each class with the hexcode (only for debugging purposes)
-     * @param outfilePath output file
-     * @throws IOException
-     */
-/*    public static void fromJava(boolean hexcode, String outfilePath) throws IOException {
-        File f = new File(outfilePath);
-        if (f.exists()) {
-            f.delete();
-        }
-        f.createNewFile();
-        FileOutputStream fw = new FileOutputStream(f);
-        OutputStreamWriter ow = new OutputStreamWriter(fw, "utf-8");
-        int maxChar;
-        maxChar = Character.MAX_VALUE;
-
-        ow.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 
-        "<classes>\n");
-        // loop over the first Unicode plane
-        for (int code = Character.MIN_VALUE; code <= maxChar; ++code) {
-            
-            // skip surrogate area
-            if (code == Character.MIN_SURROGATE) {
-                code = Character.MAX_SURROGATE;
-                continue;
-            }
-
-            // we are only interested in LC, UC and TC letters which are their own LC,
-            // and in 'other letters'
-            if (!(((Character.isLowerCase(code) || Character.isUpperCase(code)
-                    || Character.isTitleCase(code))
-                    && code == Character.toLowerCase(code))
-                    || Character.getType(code) == Character.OTHER_LETTER)) {
-                continue;
-            }
-            
-            // skip a number of blocks
-            Character.UnicodeBlock ubi = Character.UnicodeBlock.of(code);
-            if (ubi.equals(Character.UnicodeBlock.SUPERSCRIPTS_AND_SUBSCRIPTS)
-                    || ubi.equals(Character.UnicodeBlock.LETTERLIKE_SYMBOLS)
-                    || ubi.equals(Character.UnicodeBlock.ALPHABETIC_PRESENTATION_FORMS)
-                    || ubi.equals(Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS)
-                    || ubi.equals(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)
-                    || ubi.equals(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A)
-                    || ubi.equals(Character.UnicodeBlock.HANGUL_SYLLABLES)) {
-                continue;
-            }
-
-            int uppercode = Character.toUpperCase(code);
-            int titlecode = Character.toTitleCase(code);
-            StringBuilder s = new StringBuilder();
-            if (hexcode) {
-                s.append("0x" + Integer.toHexString(code) + " ");
-            }
-            s.append(Character.toChars(code));
-            if (uppercode != code) {
-                s.append(Character.toChars(uppercode));
-            }
-            if (titlecode != code && titlecode != uppercode) {
-                s.append(Character.toChars(titlecode));
-            }
-            ow.write(s.toString() + "\n");
-        }
-        ow.write("</classes>\n");
-        ow.flush();
-        ow.close();
-    }
-*/    
-    
-    /**
-     * The column numbers in the UCD file
-     */
-    public static final int UNICODE = 0, GENERAL_CATEGORY = 2, SIMPLE_UPPERCASE_MAPPING = 12,
-    SIMPLE_LOWERCASE_MAPPING = 13, SIMPLE_TITLECASE_MAPPING = 14, NUM_FIELDS = 15;
-    
-    /**
-     * Generate classes.xml from Unicode Character Database files
-     * @param hexcode whether to prefix each class with the hexcode (only for debugging purposes)
-     * @param unidataPath path to the directory with UCD files  
-     * @param outfilePath output file
-     * @throws IOException if the input files are not found
-     */
-    public static void fromUCD(boolean hexcode, String unidataPath, String outfilePath)
-    throws IOException {
-        File unidata = new File(unidataPath);
-        
-        File f = new File(outfilePath);
-        if (f.exists()) {
-            f.delete();
-        }
-        f.createNewFile();
-        FileOutputStream fw = new FileOutputStream(f);
-        OutputStreamWriter ow = new OutputStreamWriter(fw, "utf-8");
-        
-        File in = new File(unidata, "Blocks.txt");
-        FileInputStream inis = new FileInputStream(in);
-        InputStreamReader insr = new InputStreamReader(inis, "utf-8");
-        BufferedReader inbr = new BufferedReader(insr);
-        Map blocks = new HashMap();
-        for (String line = inbr.readLine(); line != null; line = inbr.readLine()) {
-            if (line.startsWith("#") || line.matches("^\\s*$")) {
-                continue;
-            }
-            String[] parts = line.split(";");
-            String block = parts[1].trim();
-            String[] indices = parts[0].split("\\.\\.");
-            int[] ind = {Integer.parseInt(indices[0], 16), Integer.parseInt(indices[1], 16)};
-            blocks.put(block, ind);
-        }
-        inbr.close();
-
-        in = new File(unidata, "UnicodeData.txt");
-        inis = new FileInputStream(in);
-        insr = new InputStreamReader(inis, "utf-8");
-        inbr = new BufferedReader(insr);
-        int maxChar;
-        maxChar = Character.MAX_VALUE;
-
-        ow.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-                 + "<classes>\n");
-        for (String line = inbr.readLine(); line != null; line = inbr.readLine()) {
-            String[] fields = line.split(";", NUM_FIELDS);
-            int code = Integer.parseInt(fields[UNICODE], 16);
-            if (code > maxChar) {
-                break;
-            }
-            if (((fields[GENERAL_CATEGORY].equals("Ll") || fields[GENERAL_CATEGORY].equals("Lu")
-                            || fields[GENERAL_CATEGORY].equals("Lt"))
-                        && ("".equals(fields[SIMPLE_LOWERCASE_MAPPING])
-                                || fields[UNICODE].equals(fields[SIMPLE_LOWERCASE_MAPPING])))
-                    || fields[GENERAL_CATEGORY].equals("Lo")) {
-                String[] blockNames = {"Superscripts and Subscripts",
-                                       "Letterlike Symbols",
-                                       "Alphabetic Presentation Forms",
-                                       "Halfwidth and Fullwidth Forms",
-                                       "CJK Unified Ideographs",
-                                       "CJK Unified Ideographs Extension A",
-                                       "Hangul Syllables"};
-                int j;
-                for (j = 0; j < blockNames.length; ++j) {
-                    int[] ind = (int[]) blocks.get(blockNames[j]);
-                    if (code >= ind[0] && code <= ind[1]) {
-                        break;
-                    }
-                }
-                if (j < blockNames.length) {
-                    continue;
-                }
-            
-                int uppercode = -1, titlecode = -1;
-                if (!"".equals(fields[SIMPLE_UPPERCASE_MAPPING])) {
-                    uppercode = Integer.parseInt(fields[SIMPLE_UPPERCASE_MAPPING], 16);
-                }
-                if (!"".equals(fields[SIMPLE_TITLECASE_MAPPING])) {
-                    titlecode = Integer.parseInt(fields[SIMPLE_TITLECASE_MAPPING], 16);
-                }
-                StringBuffer s = new StringBuffer();
-                if (hexcode) {
-                    s.append("0x" + fields[UNICODE].replaceFirst("^0+", "").toLowerCase() + " ");
-                }
-                // s.append(Character.toChars(code));
-                /* This cast only works correctly when we do not exceed Character.MAX_VALUE */
-                s.append((char) code);
-                if (uppercode != -1 && uppercode != code) {
-                    // s.append(Character.toChars(uppercode));
-                    s.append((char) uppercode);
-                }
-                if (titlecode != -1 && titlecode != code && titlecode != uppercode) {
-                    // s.append(Character.toChars(titlecode));
-                    s.append((char) titlecode);
-                }
-                ow.write(s.toString() + "\n");
-            }
-        }
-        ow.write("</classes>\n");
-        ow.flush();
-        ow.close();
-        inbr.close();
-    }
-
-    /**
-     * Generate classes.xml from XeTeX's Unicode letters file
-     * @param hexcode whether to prefix each class with the hexcode (only for debugging purposes)
-     * @param lettersPath path to XeTeX's Unicode letters file unicode-letters-XeTeX.tex  
-     * @param outfilePath output file
-     * @throws IOException
-     */
-/*    public static void fromTeX(boolean hexcode, String lettersPath, String outfilePath)
-      throws IOException {
-        File in = new File(lettersPath);
-
-        File f = new File(outfilePath);
-        if (f.exists()) {
-            f.delete();
-        }
-        f.createNewFile();
-        FileOutputStream fw = new FileOutputStream(f);
-        OutputStreamWriter ow = new OutputStreamWriter(fw, "utf-8");
-
-        FileInputStream inis = new FileInputStream(in);
-        InputStreamReader insr = new InputStreamReader(inis, "utf-8");
-        BufferedReader inbr = new BufferedReader(insr);
-
-        ow.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 
-        "<classes>\n");
-        for (String line = inbr.readLine(); line != null; line = inbr.readLine()) {
-            String[] codes = line.split("\\s+");
-            if (!(codes[0].equals("\\L") || codes[0].equals("\\l"))) {
-                continue;
-            }
-            if (codes.length == 3) {
-                ow.write("\"" + line + "\" has two codes");
-                continue;
-            }
-            if (codes[0].equals("\\l") && codes.length != 2) {
-                ow.write("\"" + line + "\" should have one code");
-                continue;
-            }
-            else if (codes[0].equals("\\L") && codes.length != 4) {
-                ow.write("\"" + line + "\" should have three codes");
-                continue;
-            }
-            if (codes[0].equals("\\l") || (codes[0].equals("\\L") && codes[1].equals(codes[3]))) {
-                StringBuilder s = new StringBuilder();
-                if (hexcode) {
-                    s.append("0x" + codes[1].replaceFirst("^0+", "").toLowerCase() + " ");
-                }
-                s.append((char) Integer.parseInt(codes[1], 16));
-                if (codes[0].equals("\\L")) {
-                    s.append((char) Integer.parseInt(codes[2], 16));
-                }
-                ow.write(s.toString() + "\n");
-            }
-        }
-        ow.write("</classes>\n");
-        ow.flush();
-        ow.close();
-        inbr.close();
-    }
-*/
-    
-    /**
-     * @param args [--hexcode] [--java|--ucd|--tex] [--out outfile] infile
-     * @throws IOException if the input file cannot be found
-     */
-    public static void main(String[] args) throws IOException {
-        String type = "ucd", prefix = "--", infile = null, outfile = CLASSES_XML;
-        boolean hexcode = false;
-        for (int i = 0; i < args.length; ++i) {
-            if (args[i].startsWith(prefix)) {
-                String option = args[i].substring(prefix.length());
-                if (option.equals("java") || option.equals("ucd") || option.equals("tex")) {
-                    type = option;
-                } else if (option.equals("hexcode")) {
-                    hexcode = true;
-                } else if (option.equals("out")) {
-                    outfile = args[++i];
-                } else {
-                    System.err.println("Unknown option: " + option);
-                    System.exit(1);
-                }
-            } else {
-                if (infile != null) {
-                    System.err.println("Only one non-option argument can be given, for infile");
-                    System.exit(1);
-                }
-                infile = args[i];
-            }
-        }
-        
-        if (type.equals("java")) {
-            if (infile != null) {
-                System.err.println("Type java does not allow an infile");
-                System.exit(1);
-            }
-        } else {
-            if (infile == null) {
-                System.err.println("Types ucd and tex require an infile");
-                System.exit(1);
-            }
-        }
-/*        if (type.equals("java")) {
-            fromJava(hexcode, outfile);
-        } else
- */     
-        if (type.equals("ucd")) {
-            fromUCD(hexcode, infile, outfile);
-/*        } else if (type.equals("tex")) {
-            fromTeX(hexcode, infile, outfile);
-*/        
-            } else {
-            System.err.println("Unknown type: " + type + ", nothing done");
-            System.exit(1);
-        }
-    }
-
-}
index bf5c297581f32a532c49f09619fdb3dd00e55ff8..056a533a8ae8f692251411606f48ee0a7d86c969 100644 (file)
@@ -1,4 +1,28 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more       -->
+<!-- contributor license agreements.  See the NOTICE file distributed with    -->
+<!-- this work for additional information regarding copyright ownership.      -->
+<!-- The ASF licenses this file to You under the Apache License, Version 2.0  -->
+<!-- (the "License"); you may not use this file except in compliance with     -->
+<!-- the License.  You may obtain a copy of the License at                    -->
+<!--                                                                          -->
+<!--      http://www.apache.org/licenses/LICENSE-2.0                          -->
+<!--                                                                          -->
+<!-- Unless required by applicable law or agreed to in writing, software      -->
+<!-- distributed under the License is distributed on an "AS IS" BASIS,        -->
+<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
+<!-- See the License for the specific language governing permissions and      -->
+<!-- limitations under the License.                                           -->
+
+<!-- $Id$ -->
+
+<!-- !!! THIS IS A GENERATED FILE !!!             -->
+<!-- If updates are needed, then:                 -->
+<!-- * run 'ant codegen-hyphenation-classes',     -->
+<!--   which will generate a new file classes.xml -->
+<!--   in 'src/java/org/apache/fop/hyphenation'   -->
+<!-- * commit the changed file                    -->
+
 <classes>
 aA
 bB