
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