All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.enhydra.xml.xmlc.codegen.IndentWriter Maven / Gradle / Ivy

The newest version!
/*
 * Enhydra Java Application Server Project
 * 
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License on
 * the Enhydra web site ( http://www.enhydra.org/ ).
 * 
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 
 * the License for the specific terms governing rights and limitations
 * under the License.
 * 
 * The Initial Developer of the Enhydra Application Server is Lutris
 * Technologies, Inc. The Enhydra Application Server and portions created
 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s):
 * 
 * $Id: IndentWriter.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
 */

package org.enhydra.xml.xmlc.codegen;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;

import org.enhydra.xml.xmlc.XMLCError;

/**
 * Class to print lines with indentation.  Overrides all print methods
 * to do indentation at the start of a line.
 */
public class IndentWriter extends PrintWriter {
    /*
     * Are we at the beginning of the line.
     */
    private boolean fAtBOLN = true;
    
    /**
     * Standard indentation amount.
     */
    private static int INDENT_SIZE = 4;

    /** 
     * Current indentation level (in characters units).
     */
    private int fIndent = 0;

    /**
     * Stack of additional indentation that has 
     */
    private int fAdditionalIndent = 0;

    /**
     * Stack of additional indentation amounts that have been 
     * added (entries are Integer).
     */
    private ArrayList fAdditionalIndentStack;

    /**
     * Generate an error if indentation is not zero on close.
     */
    private boolean fZeroCheck = true;

    /**
     * Current indentation prefix.
     */
    private String fIndentPrefix = "";
    
    /**
     * Static string that is used as a quick way to get a certain indent
     * level.  Indent strings are generated by taking substrings of this
     * string.  This string is grown as needed.
     */
    private static String fIndentSourceString
        = "                                                               ";

    /**
     * Constructor from a Writer
     */
    public IndentWriter(Writer writer) {
        super(writer);
    }

    /**
     * Constructor from a Writer
     */
    public IndentWriter(Writer writer,
                        boolean autoflush) {
        super(writer, autoflush);
    }

    /**
     * Set value of zero-check flag.  If true, then generate an error if
     * indentation is not zero on close.  Default is true.
     */
    public void setZeroCheck(boolean value) {
        fZeroCheck = value;
    }

    /**
     * Get value of zero-check flag.
     */
    public boolean getZeroCheck() {
        return fZeroCheck;
    }

    /**
     * Utility to open file.
     */
    private static Writer openFile(File src, String enc) throws IOException {
        // Create directory if it doesn't exist
        String parent = src.getParent();
        if (parent != null) {
            new File(parent).mkdirs();
        }
	if (enc == null) {
            return new PrintWriter(new BufferedOutputStream(new FileOutputStream(src)));
	} else {
            return new PrintWriter(new OutputStreamWriter(
		    new BufferedOutputStream(new FileOutputStream(src)), enc));
	}
	    

    }

    /**
     * Constructor given a file name.  If the directory containing
     * the file doesn't exist, it is created.
     */
    public IndentWriter(File src) throws IOException {
        super(openFile(src, null));
    }

    /**
     * Constructor given a file name and an encoding.  If the directory containing
     * the file doesn't exist, it is created.
     */
    public IndentWriter(File src, String enc) throws IOException {
        super(openFile(src, enc));
    }

    /**
     * Called when through generating code.  Close the contained stream and
     * make sure that indentation is zero.  If not, we might have screawed
     * something up.
     * @param ignoreErrors If true, ignore any errors and don't check
     *  for zero.  This should be used only when calling this method while
     *  handling an error.
     */
    public void close(boolean ignoreErrors) {
        if (ignoreErrors) {
            try {
                super.close();
            } catch (Throwable err) {
                // ignore
            }
        } else {
            super.close();
            checkZero();
        }
    }

    /**
     * Flush output; indentation must be zero.
     */
    public void flush() {
        super.flush();
        checkZero();
    }

    /**
     * Get an indentation from the source string, growing source as needed.
     */
    private static String getIndentString(int numChars) {
        // Grow if needed; coded to avoid sync
        while (fIndentSourceString.length() < numChars) {
            fIndentSourceString += fIndentSourceString;
        }
        return fIndentSourceString.substring(0, numChars);
    }

    /**
     * Set the current indentation string.
     */
    private void setIndentPrefix() {
        fIndentPrefix = getIndentString(fIndent);
    }

    /**
     * Check that the indentation is zero.
     */
    private void checkZero() {
        if (fZeroCheck && (fIndent != 0)) {
            // This could indicate something more serious.
            throw new XMLCError("code indentation not zero at end");
        }
    }

    /**
     * Increase indentation level.
     */
    public final void enter() {
        fIndent += INDENT_SIZE;
        setIndentPrefix();
    }

    /**
     * Decrease indentation level.
     */
    public final void leave() {
        fIndent -= INDENT_SIZE;
        if (fIndent < 0) {
            throw new XMLCError("identation level underflow");
        }
        setIndentPrefix();
    }

    /**
     * Get the indentation level.
     */
    public final int getIndentLevel() {
        return fIndent;
    }

    /**
     * Push an additional amount of indentation, in an arbitrary number of
     * characters.  This is used for aligning parameters, etc, which
     * don't fall on the block-level indent boundry.
     */
    final public void pushAdditionalIndent(int numChars) {
        if (fAdditionalIndentStack == null) {
            fAdditionalIndentStack = new ArrayList();
        }
        fAdditionalIndentStack.add(new Integer(numChars));
        fIndent += numChars;
        setIndentPrefix();
    }

    /**
     * Remove the last amount of additional indentation that was added.
     */
    public final void popAdditionalIndent() {
        if ((fAdditionalIndentStack == null) || (fAdditionalIndentStack.size() == 0)) {
            throw new XMLCError("additional identation stack underflow");
        }
        Integer numChars = (Integer)fAdditionalIndentStack.remove(fAdditionalIndentStack.size()-1);
        fIndent -= numChars.intValue();
        if (fIndent < 0) {
            throw new XMLCError("identation level underflow");
        }
        setIndentPrefix();
    }

    /**
     * Are we at the beginning of a line?
     */
    public boolean atBOLN() {
        return fAtBOLN;
    }

    /**
     * Write the current indentation and clear BOL flag.
     */
    private void printIndent() {
        super.print(fIndentPrefix);
        fAtBOLN = false;
    }

    /**
     * Print a prefix for a line.  If not at the beginning of a line, start a
     * new one.  Prefix will preceed indentation.
     */
    protected void printPrefix(String prefix) {
        if (!fAtBOLN) {
            println();
        }
        super.print(prefix);
        printIndent();
    }

    /**
     * Print a boolean value.
     * @see java.io.Writer
     */
    public void print(boolean b) {
        if (fAtBOLN) {
            printIndent();
        }
        super.print(b);
    }

    /**
     * Print a character.
     * @see java.io.Writer
     */
    public void print(char c) {
        if (fAtBOLN) {
            printIndent();
        }
        super.print(c);
    }

    /**
     * Print a long integer.
     * @see java.io.Writer
     */
    public void print(long l) {
        if (fAtBOLN) {
            printIndent();
        }
        super.print(l);
    }

    /**
     * Print a floating-point number.
     * @see java.io.Writer
     */
    public void print(float f) {
        if (fAtBOLN) {
            printIndent();
        }
        super.print(f);
    }

    /**
     * Print a double-precision floating-point number.
     * @see java.io.Writer
     */
    public void print(double d) {
        if (fAtBOLN) {
            printIndent();
        }
        super.print(d);
    }

    /**
     * Print an array of characters, indenting at the beginning of lines.
     * The string is split at embedded newlines.
     * @see java.io.Writer
     */
    public void print(char[] str) {
        int idx = 0;
        int strlen = str.length;
        int nlIdx;

        // Write string, breaking at 
        while (idx < strlen) {
            if (fAtBOLN) {
                printIndent();
            }
            // Find next new line
            for (nlIdx = idx; (nlIdx < strlen) && (str[nlIdx] != '\n'); nlIdx++) {
            }
            if (nlIdx < strlen) {
                write(str, idx, nlIdx-idx);
                println();  // Writes platform-dependent EOLN
            } else {
                write(str, idx, strlen-idx);
            }
            idx = nlIdx+1;
            fAtBOLN = true;  // Last character was a newline.
        }
    }

    /**
     * Print a string, indenting at the beginning of lines.
     * The string is split at embedded newlines.
     * @see java.io.Writer
     */
    public void print(String str) {
        int idx = 0;
        int strlen = str.length();
        int nlIdx;

        // Write string upto last newline.
        while ((idx < strlen) && ((nlIdx = str.indexOf('\n', idx)) >= 0)) {
            if (fAtBOLN) {
                printIndent();
            }
            write(str, idx, nlIdx-idx);
            println();  // Writes platform-dependent EOLN
            idx = nlIdx+1;
        }
        
        // Write characters following the last newline.  If there
        // were no newlines in the string, this writes the entire string.
        if (idx < strlen) {
            if (fAtBOLN) {
                printIndent();
            }
            write(str, idx, strlen-idx);
        }
    }

    /**
     * Print an object.
     * @see java.io.Writer
     */
    public void print(Object obj) {
        if (fAtBOLN) {
            printIndent();
        }
        super.print(obj);
    }

    /**
     * Terminate the current line by writing the line separator string.
     * @see java.io.Writer
     */
    public void println() {
	super.println();
        fAtBOLN = true;
    }

    /**
     * Write an array of strings, one line per string. Indenting at the
     * beginning of the line.  The string is split at embedded newlines.
     * @see java.io.Writer
     */
    public void println(String[] strs) {
        for (int i = 0; i < strs.length; i++) {
            println(strs[i]);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy