You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/05/25 06:28:31 UTC

svn commit: r947912 [1/5] - in /openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools: ./ ant/ converter/ parser/ util/

Author: ppoddar
Date: Tue May 25 04:28:30 2010
New Revision: 947912

URL: http://svn.apache.org/viewvc?rev=947912&view=rev
Log:
Add a Java2HTML conversion facility that we can tweak

Added:
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/CommandProcessor.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/ant/
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/ant/Java2HTMLConverterTask.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/HTMLTokenRenderer.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2HTMLConverter.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2TextConverter.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/ParseTokenListener.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/PlainTokenRenderer.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/SourceRenderer.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/TokenRenderer.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/parser/
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/parser/JavaLexer.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/parser/JavaParser.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/util/
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/util/TextProcessingUtility.java   (with props)
    openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/util/URIUtils.java   (with props)

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/CommandProcessor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/CommandProcessor.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/CommandProcessor.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/CommandProcessor.java Tue May 25 04:28:30 2010
@@ -0,0 +1,357 @@
+/*
+ * 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.    
+ */
+package openbook.tools;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Processes options.
+ * <br>
+ * User can register a set of command options. Then this processor will parse a set of Strings to
+ * store the values for each of the registered options as well as optionally any unrecognized
+ * option values.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class CommandProcessor {
+    private final Map<Option, String> registeredOptions = new HashMap<Option,String>();
+    private final Set<Option> unregisteredOptions = new HashSet<Option>();
+    private boolean allowsUnregisteredOption = true;
+    
+    /**
+     * Set the option values from the given arguments.
+     * All elements of the given array is <em>not</em> consumed,
+     * only till the index that appears to be a valid option.
+     * 
+     * @see #lastIndex(String[])
+     * 
+     * @param args an array of arguments.
+     * 
+     * @return the array elements that are not consumed.
+     */
+    public String[] setFrom(String[] args) {
+        return setFrom(args, 0, args != null ? lastIndex(args) : 0);
+    }
+    
+    /**
+     * Set the option values from the given arguments between the given indices.
+     * 
+     * @see #lastIndex(String[])
+     * 
+     * @param args an array of arguments.
+     * 
+     * @return the array elements that are not consumed.
+     */
+    public String[] setFrom(String[] args, int from, int to) {
+        if (args == null) 
+            return null;
+        if (args.length == 0)
+            return new String[0];
+        assertValidIndex(from, args, "Initial index " + from + " is an invalid index to " + Arrays.toString(args));
+        assertValidIndex(to, args, "Last index " + to + " is an invalid index to " + Arrays.toString(args));
+            
+        int i = from;
+        for (; i < to; i++) {
+            String c = args[i];
+            Option command = findCommand(c);
+            if (command == null) {
+                throw new IllegalArgumentException(c + " is not a recongined option");
+            }
+            if (command.requiresInput()) {
+                i++;
+            }
+            if (i > to) {
+                throw new IllegalArgumentException("Command " + c + " requires a value, but no value is specified");
+            }
+            registeredOptions.put(command, args[i]);
+        }
+        String[] remaining = new String[args.length-to];
+        System.arraycopy(args, i, remaining, 0, remaining.length);
+        return remaining;
+    }
+    
+    /**
+     * Gets the last index in the given array that can be processed as an option.
+     * The array elements are sequentially tested if they are a valid option name 
+     * (i.e. starts with - character) and if valid then the next element is consumed
+     * as value, if the option requires a value. The search ends when either 
+     * the array is exhausted or encounters elements that are not options. 
+     * 
+     * @param args an array of arguments
+     * @return the last index that will/can be consumed by this processor.
+     */
+    public int lastIndex(String[] args) {
+        int i = 0;
+        for (; i < args.length; i++) {
+            if (Option.isValidName(args[i])) {
+                Option cmd = findCommand(args[i]);
+                if (cmd != null) {
+                    if (cmd.requiresInput()) {
+                        i++;
+                    }
+                    continue;
+                }
+            }
+            break;
+        }
+        return i;
+    }
+    
+    /**
+     * Register the given aliases as a command option.
+     * 
+     * @param requiresValue if true then the option must be specified with a value.
+     * @param aliases strings to recognize this option. Each must begin with a dash character.
+     * 
+     * @return the command that is registered
+     */
+    public Option register(boolean requiresValue, String...aliases) {
+        Option option = new Option(requiresValue, aliases);
+        registeredOptions.put(option, null);
+        return option;
+    }
+    
+    /**
+     * Finds a command with the given name.
+     * If no command has been registered with the given name, but this processor
+     * allows unrecognized options, then as a result of this call, the
+     * unknown name is registered as an option.
+     *  
+     * @param option a command alias.
+     * 
+     * @return null if the given String is not a valid command option name.
+     * 
+     */
+    public Option findCommand(String option) {
+        if (!Option.isValidName(option))
+            return null;
+        for (Option registeredOption : registeredOptions.keySet()) {
+            if (registeredOption.match(option))
+                return registeredOption;
+        }
+        for (Option unregisteredOption : unregisteredOptions) {
+            if (unregisteredOption.match(option))
+                return unregisteredOption;
+        }
+        if (allowsUnregisteredOption) {
+            Option cmd = new Option(option);
+            unregisteredOptions.add(cmd);
+            return cmd;
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Gets all the unrecognized command options.
+     * 
+     * @return empty set if no commands are unrecognized.
+     */
+    public Set<Option> getUnregisteredCommands() {
+        return Collections.unmodifiableSet(unregisteredOptions);
+    }
+    
+    <T> void assertValidIndex(int i, T[] a, String message) {
+        if  (i <0 || (a != null && i >= a.length))
+            throw new ArrayIndexOutOfBoundsException(message);
+    }
+    
+    /**
+     * Gets value of the option matching the given alias.
+     *   
+     * @param alias an alias.
+     * 
+     * @return value of the given option.
+     */
+    public String getValue(String alias) {
+        Option cmd = findCommand(alias);
+        return getValue(cmd);
+    }
+    
+    /**
+     * Gets value of the given option.
+     * 
+     * @param opt an option.
+     * 
+     * @return value of the given option.
+     */
+    String getValue(Option opt) {
+        String val = registeredOptions.get(opt);
+        if (val == null)
+            val = opt.getDefaultValue();
+        return val;
+    }
+    
+    /**
+     * @return the allowsUnregisteredOption
+     */
+    public boolean getAllowsUnregisteredOption() {
+        return allowsUnregisteredOption;
+    }
+
+    /**
+     * @param allowsUnregisteredOption the allowsUnregisteredOption to set
+     */
+    public void setAllowsUnregisteredOption(boolean allowsUnregisteredOption) {
+        this.allowsUnregisteredOption = allowsUnregisteredOption;
+    }
+    
+    /**
+     * A simple immutable object represents meta-data about a command option.
+     *  
+     * @author Pinaki Poddar
+     *
+     */
+    public static class Option {
+        private static final String DASH = "-";
+        
+        /**
+         * Affirms if the given string can be a valid option name.
+         * An option name always starts with dash and must be followed by at least one character.
+         */
+        public static boolean isValidName(String s) {
+            return s != null && s.startsWith(DASH) && s.length() > 1;
+        }
+        
+        /**
+         * Possible names of this command option.
+         * All aliases must start with a dash (<code>-</code>). 
+         */
+        private String[] aliases;
+        
+        /**
+         * Does the option require a value?
+         */
+        private boolean requiresInput;
+        
+        /**
+         * A default value for this option.
+         */
+        private String defValue;
+        
+        /**
+         * A description String.
+         */
+        private String _description = "";
+        
+        /**
+         * Create a command with given aliases. This option requires a value.
+         *  
+         * @param aliases strings each must start with a dash (<code>-</code>).  
+         */
+        public Option(String... aliases) {
+            this(true, aliases);
+        }
+        
+        /**
+         * Create a option with given aliases.
+         * 
+         * @param requiresInput does it require a value?
+         * @param aliases strings each must start with a dash (<code>-</code>).  
+         */
+        public Option(boolean requiresInput, String...aliases) {
+            super();
+            if (aliases == null || aliases.length == 0)
+                throw new IllegalArgumentException("Can not create command with null or empty aliases");
+            for (String alias : aliases) {
+                if (!isValidName(alias)) {
+                    throw new IllegalArgumentException("Invalid alias [" + alias + "]. " +
+                            "Aliases must start with - followded by at least one character");
+                }
+            }
+            this.aliases = aliases;
+            this.requiresInput = requiresInput;
+        }
+        
+        /**
+         * Gets the first alias as the name.
+         */
+        public String getName() {
+            return aliases[0];
+        }
+        
+        /**
+         * Sets the default value for this option.
+         * 
+         * @param v a default value.
+         * 
+         * @return this command itself.
+         * 
+         * @exception IllegalStateException if this option does not require a value.
+         */
+        public Option setDefault(String v) {
+            if (!requiresInput)
+                throw new IllegalStateException(this + " does not require a value. Can not set default value [" + v + "]");
+            defValue = v;
+            return this;
+        }
+        
+        public Option setDescription(String desc) {
+            if (desc != null) {
+                _description = desc;
+            }
+            return this;
+        }
+        
+        public String getDescription() {
+            return _description;
+        }
+        
+        /**
+         * Affirms if the given name any of the aliases.
+         * @param alias
+         * @return
+         */
+        public boolean match(String name) {
+            for (String alias : aliases) {
+                if (name.equals(alias))
+                    return true;
+            }
+            return false;
+        }
+        
+        /**
+         * Affirms if this option requires a value.
+         */
+        public boolean requiresInput() {
+            return requiresInput;
+        }
+        
+        /**
+         * Gets the default value of this option.
+         * 
+         * @return the default value. null if no default value has been set.
+         */
+        public String getDefaultValue() {
+            return defValue;
+        }
+        
+        public String toString() {
+            return getName();
+        }
+    }
+
+
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/CommandProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/ant/Java2HTMLConverterTask.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/ant/Java2HTMLConverterTask.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/ant/Java2HTMLConverterTask.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/ant/Java2HTMLConverterTask.java Tue May 25 04:28:30 2010
@@ -0,0 +1,239 @@
+/*
+ * 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.    
+ */
+package openbook.tools.ant;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import openbook.tools.converter.Java2HTMLConverter;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.taskdefs.MatchingTask;
+
+/**
+ * An ant task to run {@linkplain Java2HTMLConverter Java2HTML Converter}.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class Java2HTMLConverterTask extends MatchingTask {
+    private String sourcepath        = ".";
+    private String destDir           = ".";
+    private String extension         = "";
+    private String stylesheet        = "java.css";
+    private boolean showLineNumber   = true;
+    private boolean anchorLineNumber = false;
+    private boolean addLineBreak     = true;
+    private boolean addExplicitSpace = true;
+    private String lineNumberFormat  = "%%0%4d";
+    private boolean verbose          = false;
+    
+    private List<Arg> _args = new ArrayList<Arg>();
+    
+    public String getSourcepath() {
+        return sourcepath;
+    }
+
+    public void setSourcepath(String sourcepath) {
+        this.sourcepath = sourcepath;
+    }
+    
+    @Override
+    public void execute() throws BuildException {
+        List<String> files = getFiles();
+        List<String> args  = new ArrayList<String>();
+        args.add("-sourcepath");       args.add(sourcepath);
+        args.add("-d");                args.add(destDir);
+        args.add("-extension");        args.add(extension);
+        args.add("-verbose");          args.add(""+verbose);
+        args.add("-stylesheet");       args.add(stylesheet);
+        args.add("-showLineNumber");   args.add(""+showLineNumber);
+        args.add("-anchorLineNumber"); args.add(""+anchorLineNumber);
+        args.add("-addLineBreak");     args.add(""+addLineBreak);
+        args.add("-addExplicitSpace"); args.add(""+addExplicitSpace);
+        args.add("-lineNumberFormat"); args.add(lineNumberFormat);
+        args.add("-anchorLineNumber"); args.add(""+anchorLineNumber);
+        
+        for (Arg a : _args) {
+            args.add(a.getName());
+            args.add(a.getValue());
+        }
+        for (String file : files) {
+            args.add(file.replace(File.separatorChar, '/'));
+        }
+        try {
+            Java2HTMLConverter.main(args.toArray(new String[args.size()]));
+        } catch (Exception e) {
+            throw new BuildException(e);
+        }
+    }
+    
+    List<String> getFiles() {
+        List<String> list = new ArrayList<String>();
+        DirectoryScanner scanner = getDirectoryScanner(new File(getSourcepath()));
+        String[] files = scanner.getIncludedFiles();
+        for (String file : files) {
+            if (file.endsWith(".java")) {
+                list.add(file);
+            }
+        }
+        return list;
+    }
+    
+    public Arg createArg() {
+        Arg arg = new Arg();
+        _args.add(arg);
+        return arg;
+    }
+    
+
+    public String getDestDir() {
+        return destDir;
+    }
+
+    public void setDestDir(String destDir) {
+        this.destDir = destDir;
+    }
+
+    public boolean isVerbose() {
+        return verbose;
+    }
+
+    public void setVerbose(boolean verbose) {
+        this.verbose = verbose;
+    }
+    
+    /**
+     * @return the extension
+     */
+    public String getExtension() {
+        return extension;
+    }
+
+    /**
+     * @param extension the extension to set
+     */
+    public void setExtension(String extension) {
+        this.extension = extension;
+    }
+
+    /**
+     * @return the stylesheet
+     */
+    public String getStylesheet() {
+        return stylesheet;
+    }
+
+    /**
+     * @param stylesheet the stylesheet to set
+     */
+    public void setStylesheet(String stylesheet) {
+        this.stylesheet = stylesheet;
+    }
+
+    /**
+     * @return the showLineNumber
+     */
+    public boolean isShowLineNumber() {
+        return showLineNumber;
+    }
+
+    /**
+     * @param showLineNumber the showLineNumber to set
+     */
+    public void setShowLineNumber(boolean showLineNumber) {
+        this.showLineNumber = showLineNumber;
+    }
+
+    /**
+     * @return the anchorLineNumber
+     */
+    public boolean isAnchorLineNumber() {
+        return anchorLineNumber;
+    }
+
+    /**
+     * @param anchorLineNumber the anchorLineNumber to set
+     */
+    public void setAnchorLineNumber(boolean anchorLineNumber) {
+        this.anchorLineNumber = anchorLineNumber;
+    }
+
+    /**
+     * @return the addLineBreak
+     */
+    public boolean isAddLineBreak() {
+        return addLineBreak;
+    }
+
+    /**
+     * @param addLineBreak the addLineBreak to set
+     */
+    public void setAddLineBreak(boolean addLineBreak) {
+        this.addLineBreak = addLineBreak;
+    }
+
+    /**
+     * @return the addExplicitSpace
+     */
+    public boolean isAddExplicitSpace() {
+        return addExplicitSpace;
+    }
+
+    /**
+     * @param addExplicitSpace the addExplicitSpace to set
+     */
+    public void setAddExplicitSpace(boolean addExplicitSpace) {
+        this.addExplicitSpace = addExplicitSpace;
+    }
+
+    /**
+     * @return the lineNumberFormat
+     */
+    public String getLineNumberFormat() {
+        return lineNumberFormat;
+    }
+
+    /**
+     * @param lineNumberFormat the lineNumberFormat to set
+     */
+    public void setLineNumberFormat(String lineNumberFormat) {
+        this.lineNumberFormat = lineNumberFormat;
+    }
+    
+    public static class Arg {
+        String name;
+        String value;
+        
+        public String getName() {
+            return name;
+        }
+        public void setName(String name) {
+            this.name = name;
+        }
+        public String getValue() {
+            return value;
+        }
+        public void setValue(String value) {
+            this.value = value;
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/ant/Java2HTMLConverterTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/HTMLTokenRenderer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/HTMLTokenRenderer.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/HTMLTokenRenderer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/HTMLTokenRenderer.java Tue May 25 04:28:30 2010
@@ -0,0 +1,308 @@
+/*
+ * 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.    
+ */
+package openbook.tools.converter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import openbook.tools.parser.JavaParser;
+import openbook.tools.util.TextProcessingUtility;
+
+import org.antlr.runtime.Token;
+
+/**
+ * Renders Java source tokens as HTML tags.
+ * This renderer renders the parsed Java tokens with HTML styles.
+ * The styles of the tokens are determined by their types such as Java keywords, identifiers,
+ * comments etc. Moreover, an identifier can be a <em>custom</em> type if it matched a given
+ * list of identifiers. The actual HTML text is enclosed in &lt;span id="style"&gt;token&lt;\span&gt;
+ * to apply the style. The styles are defined in a Cascaded Style Sheet (CSS). 
+ * The cascaded style sheet by default is named <code>java.css</code>.
+ * <br>
+ * The rendering takes care of line breaks and white space in the following way to work
+ * around some limitations of Swing based HTML editor kit's usage of CSS attributes.
+ * <LI> Line Breaks: Swing Editor seems to require an explicit carriage return-line feed
+ * character to render in separate line. While a normal browser works with &lt;br&gt;
+ * tag alone. 
+ * <LI> White space: The CSS property <code>white-space</code> is sufficient for browsers
+ * to preserve white space within &lt;span&gt; tags. But Swing Editor seems to require 
+ * explicit <code>nbsp;</code> for white spaces within &lt;span&gt; tags.
+ * <br>
+ * Two boolean properties are provided to control these two properties. 
+ * <br>
+ * <LI>Line Numbering: A boolean property controls whether line numbers will be printed.
+ * Line numbers are printed in 4 digits with leading zeros, by default.
+ * <LI>Line Number Anchoring: An anchor can be specified at every line. The anchor
+ * is <code>line.nnn</code> where <code>nnn</code> is the actual line number without
+ * any leading zero.
+ * <LI> JavaDoc comment : The JavaDoc comments can use characters that if reproduced
+ * exactly in HTML output can confuse the rendering process. On the other hand, the
+ * JavaDoc tags that define an anchor in the source code or creates a hyperlink should
+ * be preserved in the HTML output. The capacity and limitation of processing HTML tages
+ * inside JavaDoc comments are described in {@linkplain TextProcessingUtility here}.
+ * 
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class HTMLTokenRenderer implements TokenRenderer {
+    private String stylesheet        = "java.css";
+    private boolean showLineNumber   = true;
+    private boolean anchorLineNumber = false;
+    private boolean addLineBreak     = true;
+    private boolean addExplicitSpace = true;
+    private String lineNumberFormat  = "%%0%4d    ";
+    
+    /**
+     * The CSS named styles.
+     */
+    public static final String CSS_CUSTOM      = "custom";
+    public static final String CSS_KEYWORD     = "keyword";
+    public static final String CSS_ANNOTATION  = "annotation";
+    public static final String CSS_ENUM        = "enum";
+    public static final String CSS_COMMENT     = "comment";
+    public static final String CSS_LITERAL     = "literal";
+    public static final String CSS_DECIMAL     = "decimal";
+    public static final String CSS_LINE_NO     = "lineno";
+    
+    private Set<String> customIdentifiers = new HashSet<String>();
+
+    public static final String NEW_LINE = "\r\n";
+    public static final String HTML_BR_TAG = "<br>";
+    public static final String HTML_SPACE = "&nbsp;";
+    
+    /**
+     * Gets a end-of-line string: a HTML &lt;br&gt; tag followed by carriage return and line feed.
+     */
+    public String endLine(int line) {
+        return addLineBreak ? HTML_BR_TAG : HTML_BR_TAG + NEW_LINE;
+    }
+
+    /**
+     * Gets a string for beginning of a new line.  
+     */
+    public String newLine(int line) {
+        String result = "";
+        if (showLineNumber) {
+            result = span(CSS_LINE_NO, fillWhiteSpace(String.format(lineNumberFormat, line)));
+        }
+        if (anchorLineNumber) {
+            result = "<A name=" + quote("line."+line) + ">" + result + "</A>";
+        }
+        return result;
+    }
+
+    @Override
+    public String render(int decision, Token token) {
+        String text = token.getText();
+        String result = "";
+        int type = token.getType();
+        switch (type) {
+        case JavaParser.Identifier:
+        case 73: // annotation symbol @
+            if (customIdentifiers.contains(text)) {
+                result = span(CSS_CUSTOM, text);
+            } else if (decision == 66 || decision == 14) {
+                result = span(CSS_ANNOTATION, text);
+            } else if (decision == 28) {
+                result = span(CSS_ENUM, text);
+            } else {
+                result = text;
+            }
+            break;
+        case JavaParser.COMMENT:
+        case JavaParser.LINE_COMMENT :
+            result = span(CSS_COMMENT, TextProcessingUtility.replaceHTMLSpecialCharacters(text));
+            break;
+        case JavaParser.StringLiteral :
+        case JavaParser.CharacterLiteral:
+            result = span(CSS_LITERAL, text);
+            break;
+        case JavaParser.DecimalLiteral:
+        case JavaParser.HexDigit:
+        case JavaParser.HexLiteral:
+            result = span(CSS_DECIMAL, text);
+            break;
+        default:
+            if (isWhiteSpace(text)) {
+                result = fillWhiteSpace(text);
+            } else if (text.length() == 1) {
+                if (text.charAt(0) == '>') {
+                    result = "&gt;";
+                } else if (text.charAt(0) == '<') {
+                    result = "&lt;";
+                } else {
+                    result = text;
+                }
+            } else {
+                result = span(CSS_KEYWORD, text);
+            }
+        }
+        return result;
+    }
+    
+    String span(String id, String txt) {
+        return "<span id=" + quote(id) + ">" + txt + "</span>";
+    }
+    
+    String quote(String s) {
+        return "\""+s+"\"";
+    }
+    
+    boolean isWhiteSpace(String txt) {
+        for (int i = 0; i < txt.length(); i++) {
+            if (!Character.isWhitespace(txt.charAt(i)))
+               return false;
+        }
+        return true;
+    }
+    
+    String fillWhiteSpace(String txt) {
+        StringBuilder space = new StringBuilder();
+        for (int i = 0; i < txt.length(); i++) {
+            char ch = txt.charAt(i);
+            if (ch != '\r' && ch != '\n')
+                space.append(addExplicitSpace ? HTML_SPACE : ch);
+        }
+        return space.toString();
+    }
+    
+
+    /**
+     * Gets the opening &lt;BODY&gt; and &lt;HTML&gt; tags and the &lt;link type="stylesheet"&gt; clause.
+     */
+    public String getPrologue() {
+        return insertLines(
+                "<HTML>", 
+                "<HEAD>", 
+                "<link rel="+ quote("stylesheet")+ " type=" + quote("text/css") + " href=" + quote(stylesheet) + ">",
+                "</HEAD>",
+                "<BODY>");
+    }
+    
+    /**
+     * Gets the closing &lt;BODY&gt; and &lt;HTML&gt; tags
+     */
+    public String getEpilogue() {
+        return insertLines(" ", "</BODY>", "</HTML>");
+    }
+
+    private String insertLines(String...lines) {
+        StringBuilder buf = new StringBuilder();
+        for (String line : lines) {
+            if (buf.length() != 0) buf.append(NEW_LINE);
+            buf.append(line);
+        }
+        return buf.toString();
+    }
+
+    // Bean Style setters for auto-configuration
+    
+    /**
+     * Gets the stylesheet to be linked at HTML output. 
+     */
+    public String getStylesheet() {
+        return stylesheet;
+    }
+
+    /**
+     * Sets the stylesheet to be linked at the HTML output.
+     */
+    public void setStylesheet(String stylesheet) {
+        this.stylesheet = stylesheet;
+    }
+
+    /**
+     * Affirms if a line number will be added in HTML output.
+     */
+    public boolean getShowLineNumber() {
+        return showLineNumber;
+    }
+
+    /**
+     * Sets if a line number will be added in HTML output.
+     */
+    public void setShowLineNumber(boolean showLineNumber) {
+        this.showLineNumber = showLineNumber;
+    }
+
+    /**
+     * Affirms if an anchor will be created on every line.
+     */
+    public boolean getAnchorLineNumber() {
+        return anchorLineNumber;
+    }
+
+    /**
+     * Sets if an anchor will be created on every line.
+     */
+    public void setAnchorLineNumber(boolean anchorLineNumber) {
+        this.anchorLineNumber = anchorLineNumber;
+    }
+
+    /**
+     * Affirms if explicit line break (carriage return and line feed) will be added  
+     * at the HTML output.
+     * 
+     * @see #endLine(int)
+     */
+    public boolean getAddLineBreak() {
+        return addLineBreak;
+    }
+
+    /**
+     * Sets if explicit line break (carriage return and line feed) will be added  
+     * at the HTML output.
+     * 
+     * @see #endLine(int)
+     */
+    public void setAddLineBreak(boolean addLineBreak) {
+        this.addLineBreak = addLineBreak;
+    }
+
+    /**
+     * Affirms if explicit <code>&nbsp;</code> will be added at the HTML output.
+     */
+    public boolean getAddExplicitSpace() {
+        return addExplicitSpace;
+    }
+
+    /**
+     * Sets if explicit <code>&nbsp;</code> will be added at the HTML output.
+     */
+    public void setAddExplicitSpace(boolean addSpace) {
+        this.addExplicitSpace = addSpace;
+    }
+
+    /**
+     * Gets the format string to format line number such as <code>"%%0%4d"</code>
+     * for a 4-digit number with leading zeros.
+     */
+    public String getLineNumberFormat() {
+        return lineNumberFormat;
+    }
+
+    /**
+     * Sets the format string to format line number such as <code>"%%0%4d"</code>
+     * for a 4-digit number with leading zeros.     
+     */
+    public void setLineNumberFormat(String lineNumberFormat) {
+        this.lineNumberFormat = lineNumberFormat;
+    }   
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/HTMLTokenRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2HTMLConverter.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2HTMLConverter.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2HTMLConverter.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2HTMLConverter.java Tue May 25 04:28:30 2010
@@ -0,0 +1,73 @@
+/*
+ * 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.    
+ */
+package openbook.tools.converter;
+
+import java.io.File;
+
+import openbook.tools.CommandProcessor;
+import openbook.tools.util.URIUtils;
+
+public class Java2HTMLConverter extends SourceRenderer {
+    
+    private final HTMLTokenRenderer _renderer = new HTMLTokenRenderer();
+    
+      public static void main(String[] args) throws Exception {
+          new Java2HTMLConverter().run(args);
+      }
+      
+    @Override
+    public void registerOptions(CommandProcessor options) {
+        options.register(true, "-stylesheet").setDefault("java.css");
+        options.register(true, "-addLineBreak").setDefault("true");
+        options.register(true, "-addExplicitSpace").setDefault("true");
+        options.register(true, "-anchorLineNumber").setDefault("false");
+        options.register(true, "-showLineNumber").setDefault("true");
+        options.register(true, "-lineNumberFormat").setDefault("%%0%4d");
+    }
+    
+    @Override
+    public TokenRenderer createRenderer(CommandProcessor options, File outFile) {
+        File styleFile = null;
+        styleFile = new File(getDestinationDirectory(), options.getValue("-stylesheet"));
+        if (!styleFile.exists()) {
+            throw new IllegalArgumentException("Stylesheet file " + styleFile.getAbsolutePath() +
+                    " does not exist. Ensure that the file is available under destination directory" + 
+                    getDestinationDirectory().getAbsolutePath());
+        }
+        _renderer.setStylesheet(getRelativeStylesheet(styleFile, outFile));
+        
+        _renderer.setAddLineBreak("true".equals(options.getValue("-addLineBreak")));
+        _renderer.setAddExplicitSpace("true".equals(options.getValue("-addExplicitSpace")));
+        _renderer.setAnchorLineNumber("true".equals(options.getValue("-anchorLineNumber")));
+        _renderer.setLineNumberFormat(options.getValue("-lineNumberFormat"));
+        _renderer.setShowLineNumber("true".equals(options.getValue("-showLineNumber")));
+        return _renderer;
+    }
+    
+    
+    String getRelativeStylesheet(File styleFile,  File outFile) {
+            String stylesheetPath = styleFile.getAbsolutePath().replace(File.separatorChar, FORWARD_SLASH);
+            String outPath = outFile.getAbsolutePath().replace(File.separatorChar, FORWARD_SLASH);
+            verbose("stylesheet " + stylesheetPath);
+            verbose("output     " + outPath);
+            String rstylesheet = URIUtils.getRelativePath(stylesheetPath, outPath, ""+FORWARD_SLASH);
+            verbose("stylesheet relative " + rstylesheet);
+            return rstylesheet;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2HTMLConverter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2TextConverter.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2TextConverter.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2TextConverter.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2TextConverter.java Tue May 25 04:28:30 2010
@@ -0,0 +1,51 @@
+/*
+ * 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.    
+ */
+package openbook.tools.converter;
+
+import java.io.File;
+
+import openbook.tools.CommandProcessor;
+
+/**
+ * Converts Java Source code to plain text with optional line number.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class Java2TextConverter extends SourceRenderer {
+    
+    private final PlainTokenRenderer _renderer = new PlainTokenRenderer();
+    
+      public static void main(String[] args) throws Exception {
+          new Java2TextConverter().run(args);
+      }
+      
+    @Override
+    public void registerOptions(CommandProcessor options) {
+        options.register(true, "-showLineNumber").setDefault("true");
+        options.register(true, "-lineNumberFormat").setDefault("%%0%4d");
+    }
+    
+    @Override
+    public TokenRenderer createRenderer(CommandProcessor options, File outFile) {
+        _renderer.setLineNumberFormat(options.getValue("-lineNumberFormat"));
+        _renderer.setShowLineNumber("true".equals(options.getValue("-showLineNumber")));
+        return _renderer;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/Java2TextConverter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/ParseTokenListener.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/ParseTokenListener.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/ParseTokenListener.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/ParseTokenListener.java Tue May 25 04:28:30 2010
@@ -0,0 +1,142 @@
+/*
+ * 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.    
+ */
+package openbook.tools.converter;
+
+import java.io.PrintStream;
+import java.util.StringTokenizer;
+
+import openbook.tools.parser.JavaParser;
+
+import org.antlr.runtime.CommonToken;
+import org.antlr.runtime.Token;
+import org.antlr.runtime.debug.BlankDebugEventListener;
+
+/**
+ * A token processor to render the ANTLR tokens.
+ * 
+ * This token processor is notified as ANTLR parses every token.
+ * This processor controls a {@linkplain TokenRenderer renderer} 
+ * that renders the token.
+ *  
+ * @author Pinaki Poddar
+ *
+ */
+public class ParseTokenListener extends BlankDebugEventListener {
+    private int currentLine  = 0;
+    private int backtracking = 0;
+    private int decision;
+    private TokenRenderer _renderer;
+    private PrintStream _stream;
+    
+    /**
+     * By default, uses a {@linkplain PlainTokenRenderer}.
+     */
+    ParseTokenListener() {
+        this(new PlainTokenRenderer());
+    }
+    
+    /**
+     * Uses the given renderer and outputs to System output.
+     * 
+     * @param renderer a renderer to render the tokens.
+     */
+    ParseTokenListener(TokenRenderer renderer) {
+        this(renderer, System.out);
+    }
+    
+    /**
+     * Uses the given renderer and given outputs stream.
+     * 
+     * @param renderer a renderer to render the tokens.
+     * @param stream a output stream where the rendered strings are streamed.
+     */
+    ParseTokenListener(TokenRenderer renderer, PrintStream stream) {
+        _renderer = renderer;
+        _stream = stream;
+    }
+    
+    @Override
+    public void enterDecision(int d) {
+        backtracking += 1; 
+        decision = d;
+    } 
+    
+    @Override
+    public void exitDecision(int i) { 
+         backtracking -= 1; 
+    }
+    
+    /**
+     * A regular token is delegated to the renderer for a string representation
+     * and the resultant string is sent to the output stream.
+     */
+    @Override
+    public void consumeToken(Token token) {
+        if (backtracking > 0) return;
+        changeLine(token.getLine());
+        _stream.print(_renderer.render(decision, token));
+    }
+    
+    /**
+     * Hidden tokens are tokens that are not processed at lexical processing
+     * stage. The  most important hidden token for rendering are the tokens
+     * that represent multi-line or single line comments. The multi-line
+     * comments must be broken into individual lines for line numbering to
+     * remain consistent.
+     *  
+     */
+    @Override
+    public void consumeHiddenToken(Token token) {
+        if (this.backtracking > 0 && currentLine != 0) return;
+        int type = token.getType();
+        if (type == JavaParser.COMMENT) {
+//            LineBreakIterator lines = new LineBreakIterator(token.getText());
+            StringTokenizer linebreaker = new StringTokenizer(token.getText(), "\r\n", false);
+            int i = 0;
+//            for (String line : lines) {
+            while (linebreaker.hasMoreTokens()) {
+//                Token dummy = new CommonToken(JavaParser.COMMENT, line);
+                Token dummy = new CommonToken(JavaParser.COMMENT, linebreaker.nextToken());
+                changeLine(token.getLine() + i);
+                _stream.print(_renderer.render(decision, dummy));
+                i++;
+            }
+        } else {
+            changeLine(token.getLine()); 
+            _stream.print(_renderer.render(decision, token));
+        }
+    }
+    
+    /**
+     * If the given line is different than the current line, then asks the
+     * renderer to end the current line and start a new line. Otherwise, does nothing.
+     * 
+     * @param newline
+     */
+    void changeLine(int newline) {
+        if (newline == currentLine)
+            return;
+        _stream.print(_renderer.endLine(currentLine));
+        _stream.print(_renderer.newLine(newline));
+        if (newline != currentLine+1) {
+            System.err.println("Error is line number processing.  Line " + currentLine + " jumps to " + newline);
+        }
+        currentLine = newline;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/ParseTokenListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/PlainTokenRenderer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/PlainTokenRenderer.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/PlainTokenRenderer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/PlainTokenRenderer.java Tue May 25 04:28:30 2010
@@ -0,0 +1,75 @@
+/*
+ * 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.    
+ */
+package openbook.tools.converter;
+
+
+import org.antlr.runtime.Token;
+/**
+ * A default implementation of {@linkplain TokenRenderer} that simply prints the token.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class PlainTokenRenderer implements TokenRenderer {
+    private static final String EMPTY = "";
+    private boolean showLineNumber;
+    private String lineNumberFormat  = "%%0%4d :";
+    
+    public String endLine(int line) {
+        return EMPTY;
+    }
+
+    public String newLine(int line) {
+        return showLineNumber ? String.format(lineNumberFormat, line) : EMPTY;
+    }
+
+    public String render(int decision, Token token) {
+        return token.getText();
+    }
+
+    public String getEpilogue() {
+        return EMPTY;
+    }
+
+    public String getPrologue() {
+        return EMPTY;
+    }
+
+    public boolean getShowLineNumber() {
+        return showLineNumber;
+    }
+
+    public void setShowLineNumber(boolean showLineNumber) {
+        this.showLineNumber = showLineNumber;
+    }
+
+    /**
+     * @return the lineNumberFormat
+     */
+    public String getLineNumberFormat() {
+        return lineNumberFormat;
+    }
+
+    /**
+     * @param lineNumberFormat the lineNumberFormat to set
+     */
+    public void setLineNumberFormat(String lineNumberFormat) {
+        this.lineNumberFormat = lineNumberFormat;
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/PlainTokenRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/SourceRenderer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/SourceRenderer.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/SourceRenderer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/SourceRenderer.java Tue May 25 04:28:30 2010
@@ -0,0 +1,192 @@
+/*
+ * 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.    
+ */
+package openbook.tools.converter;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import openbook.tools.CommandProcessor;
+import openbook.tools.parser.JavaLexer;
+import openbook.tools.parser.JavaParser;
+
+import org.antlr.runtime.ANTLRInputStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.debug.DebugEventListener;
+
+/**
+ * Renders Java Source Code.
+ * 
+ * @author Pinaki Poddar
+ * 
+ */
+public abstract class SourceRenderer {
+    public final static char FORWARD_SLASH = '/'; 
+    public final static String DOT         = "."; 
+    public final static String CURRENT_DIRECTORY = "."; 
+    
+    private File _sourceDir, _destinationDir;
+    
+    boolean verbose = false;
+    /**
+     * Renders the given source files. The syntax of the command is
+     * <br>
+     * <pre>  $ java SourceRenderer [options] files </pre>
+     * For example,
+     * <pre> $ java SourceRenderer -stylesheet mystyle.css -sourcepath test -d generated/html acme/foo/SomeClass.java</pre>
+     * <p>
+     * 
+     * Recognized options are<br>
+     * <table>
+     * <TR><TD><pre>-format</pre></TD> <TD>the format of the converted output. Recognized monikers are 
+     * <code>html</code> and <code>text</code>. A fully qualified class name that implements {@link TokenRenderer} is
+     * allowed. Default is <code>html</code></TD></tr> 
+     * <TR><TD><pre>-sourcepath</pre><TD>the root of the source files. Default is the current directory</tr> 
+     * <TR><TD><pre>-d</pre><TD>the root of the generated files. Default is the current directory</tr> 
+     * </table>
+     * Besides these options, a renderer can accept more options. Any option <code>-someProperty</code>
+     * will configure the renderer if a bean-style setter method <code>setSomeProperty(String|boolean|int)</code>
+     * is available. See available documentation on the specific {@link HTMLTokenRenderer renderer}.
+     * <br>  
+     * Stylesheet file must be under destination directory.
+     * <pre>-stylesheet</pre> is relative to destination directory.
+     * 
+     * @param args command-line arguments.
+     * 
+     * @throws Exception
+     */
+    
+    protected final void run(String[] args) throws Exception {
+        CommandProcessor options = new CommandProcessor();
+        options.register(true, "-sourcepath").setDefault(CURRENT_DIRECTORY);
+        options.register(true, "-d").setDefault(CURRENT_DIRECTORY);
+        options.register(true, "-extension").setDefault("");
+        options.register(true, "-verbose").setDefault("false");
+        registerOptions(options);
+        
+        String[] inputs = options.setFrom(args); 
+        
+        _sourceDir  = new File(options.getValue("-sourcepath"));
+        _destinationDir = new File(options.getValue("-d"));
+        verbose = "true".equalsIgnoreCase(options.getValue("-verbose"));
+        for (String path : inputs) {
+            path = path.replace(File.separatorChar, FORWARD_SLASH);
+            InputStream fin = getInputStream(_sourceDir, path);
+            if (fin == null) {
+                continue;
+            }
+            
+            File outFile = new File(_destinationDir, suffix(path, options.getValue("-extension")));
+            FileOutputStream fout = createOutput(outFile);
+            if (fout == null) {
+                continue;
+            }
+            PrintStream out = new PrintStream(fout);
+
+            TokenRenderer renderer = createRenderer(options, outFile);
+            if (renderer == null) {
+                continue;
+            }
+            out.print(renderer.getPrologue());
+            render(fin, renderer, out);
+            out.println(renderer.getEpilogue());
+            out.close();
+        }
+    }
+    
+    public File getDestinationDirectory() {
+        return _destinationDir;
+    }
+    public File getSourceDirectory() {
+        return _sourceDir;
+    }
+    public abstract void registerOptions(CommandProcessor options);
+    public abstract TokenRenderer createRenderer(CommandProcessor options, File outFile);
+    
+    private void render(InputStream is, TokenRenderer renderer, PrintStream out) throws Exception {
+        ANTLRInputStream input = new ANTLRInputStream(is);
+        JavaLexer lexer = new JavaLexer(input);
+        CommonTokenStream tokens = new CommonTokenStream(lexer);
+        DebugEventListener builder = new ParseTokenListener(renderer, out);
+        JavaParser parser = new JavaParser(tokens, builder);
+        // launch the parser starting at compilation unit
+        parser.compilationUnit();
+    }
+    
+    /**
+     * Gets the input stream.
+     * 
+     * @param srcDir the root source directory.
+     * @param path the path to input file.
+     * @return
+     */
+    protected InputStream getInputStream(File srcDir, String path) {
+        File file = new File(srcDir, path); 
+        if (!file.exists()) {
+            warn("Input file " + file.getAbsolutePath() + " does not exist");
+            return null;
+        }
+        try {
+            return new FileInputStream(file);
+        } catch (Exception e) {
+            warn("Input file " + file.getAbsolutePath() + " failed due to " + e.toString());
+        }
+        return null;
+    }
+    
+    /**
+     * Gets the output stream to write to.
+     * @param file
+     * @return
+     */
+    private FileOutputStream createOutput(File file)  {
+        try {
+            file.getParentFile().mkdirs();
+            if (!file.exists())
+                file.createNewFile();
+            file.setWritable(true);
+            FileOutputStream out = new FileOutputStream(file);
+            verbose("Output " + file.toURI());
+            return out;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    
+    
+    private String suffix(String s, String suffix) {
+        if (suffix == null || suffix.isEmpty())
+            return s;
+        if (suffix.startsWith(".")) 
+            return s + suffix;
+        return s + "." + suffix;
+    }
+    
+    protected void verbose(String s) {
+        if (verbose)
+            System.err.println(s);
+    }
+    
+    protected void warn(String s) {
+        System.err.println(s);
+    }
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/SourceRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/TokenRenderer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/TokenRenderer.java?rev=947912&view=auto
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/TokenRenderer.java (added)
+++ openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/TokenRenderer.java Tue May 25 04:28:30 2010
@@ -0,0 +1,103 @@
+/*
+ * 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.    
+ */
+package openbook.tools.converter;
+
+import org.antlr.runtime.Token;
+import org.antlr.runtime.debug.DebugEventListener;
+
+/**
+ * Renders a runtime ANTLR token.
+ * {@linkplain ParseTokenListener} controls a renderer and streams the rendered Strings 
+ * to appropriate output. 
+ * <br>
+ * A renderer can define additional bean-style setter methods. They will be set before
+ * renderer is used.
+ * <br>
+ * A concrete renderer should have a no argument constructor.  
+ * <br>
+ * {@linkplain ParseTokenListener} or the <em>framework</em> calls a renderer in following sequence:
+ * <pre>
+ *    bean-style setter methods as per the user configured 
+ *    getPrologue()
+ *    for each token {
+ *       if (line is changing) {
+ *          endLine()
+ *          newLine()
+ *       }
+ *       render()
+ *    }
+ *    getEpilogue();
+ * </pre>
+
+ * @author Pinaki Poddar
+ *
+ */
+public interface TokenRenderer {
+    /**
+     * Gets a string to be added before token processing begins.
+     * <br>
+     * For example, a HTML renderer may return the opening HTML and BODY tags.
+     * A HTML render using a Cascaded Style Sheet may additionally specify
+     * the <HEAD> tag to include the style sheet.
+     */
+    public String getPrologue();
+    
+    /**
+     * Gets a string to be added after token processing ends.
+     * For example, a HTML renderer may return the closing HTML and BODY tags.
+     * 
+     */
+    public String getEpilogue();
+    
+    /**
+     * Produce a string representation of the given token.
+     * 
+     * @param decision the index of the decision (or the context) in which
+     * the current token is being processed. The index refers to ANTLR
+     * {@link DebugEventListener#enterDecision(int)}.
+     * 
+     * @param token the token to be rendered. Can be a hidden token as well.
+     * 
+     * @return a string representation of the given token.
+     */
+    public String render(int decision, Token token);
+    
+    /**
+     * Produce a string to signal beginning of a line.
+     * <br>
+     * For example, a renderer printing line numbers can produce a String with the given line number.
+     * 
+     * @param line the current line number 
+     * 
+     * @return a String can be a blank
+     */
+    public String newLine(int line);
+    
+    
+    /**
+     * Produce a string to signal end of a line.
+     * <br>
+     * For example, a renderer can produce a newline.
+     * 
+     * @param line the line being ended 
+     * 
+     * @return a String can be a blank
+     */
+    public String endLine(int line); 
+}

Propchange: openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/tools/converter/TokenRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native