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

panda.dao.sql.SqlIterator Maven / Gradle / Ivy

Go to download

Panda Core is the core module of Panda Framework, it contains commonly used utility classes similar to apache-commons.

There is a newer version: 1.8.0
Show newest version
package panda.dao.sql;

import java.io.Closeable;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.NoSuchElementException;

import panda.io.Streams;
import panda.lang.Exceptions;
import panda.lang.Strings;

/**
 * An SQL Iterator
 */
public class SqlIterator implements Iterator, Closeable {

	/** The reader that is being read. */
	private final PushbackReader reader;

	/** The current sql. */
	private StringBuilder sql = new StringBuilder();
	
	/** A flag indicating if the iterator has been fully read. */
	private boolean eof = false;

	/**
	 * Constructs an iterator of the lines for a Reader.
	 * 
	 * @param text the sql text, not null
	 * @throws IllegalArgumentException if the reader is null
	 */
	public SqlIterator(final String text) throws IllegalArgumentException {
		if (text == null) {
			throw new IllegalArgumentException("sql text must not be null");
		}
		this.reader = new PushbackReader(new StringReader(text));
	}

	/**
	 * Constructs an iterator of the lines for a Reader.
	 * 
	 * @param reader the Reader to read from, not null
	 * @throws IllegalArgumentException if the reader is null
	 */
	public SqlIterator(final Reader reader) throws IllegalArgumentException {
		if (reader == null) {
			throw new IllegalArgumentException("Reader must not be null");
		}
		this.reader = new PushbackReader(reader);
	}

	// -----------------------------------------------------------------------
	/**
	 * Indicates whether the Reader has more lines. If there is an
	 * IOException then {@link #close()} will be called on this instance.
	 * 
	 * @return true if the Reader has more lines
	 * @throws IllegalStateException if an IO exception occurs
	 */
	public boolean hasNext() {
		if (sql.length() > 0) {
			return true;
		}
		
		if (eof) {
			return false;
		}

		try {
			while (true) {
				int c = reader.read();
				if (c == Streams.EOF) {
					eof = true;
					break;
				}
				if (c == '/') {
					c = reader.read();
					if (c == Streams.EOF) {
						sql.append('/');
						break;
					}
					if (c == '*') {
						while ((c = reader.read()) != Streams.EOF) {
							if (c == '*') {
								c = reader.read();
								if (c == Streams.EOF || c == '/') {
									break;
								}
							}
						}
						if (c == Streams.EOF) {
							eof = true;
							break;
						}
					}
					else {
						sql.append('/');
					}
				}
				else if (c == '-') {
					c = reader.read();
					if (c == Streams.EOF) {
						sql.append('-');
						break;
					}
					if (c == '-') {
						while ((c = reader.read()) != Streams.EOF) {
							if (c == '\n') {
								break;
							}
						}
						if (c == Streams.EOF) {
							eof = true;
							break;
						}
					}
					else {
						sql.append('-');
					}
				}
				else if (c == '\'') {
					sql.append((char)c);
					while ((c = reader.read()) != Streams.EOF) {
						sql.append((char)c);
						if (c == '\'') {
							c = reader.read();
							if (c == Streams.EOF) {
								break;
							}
							if (c != '\'') {
								reader.unread(c);
								break;
							}
							sql.append((char)c);
						}
					}
					if (c == Streams.EOF) {
						eof = true;
						break;
					}
				}
				else if (Character.isWhitespace(c)) {
					// do not append leading space
					if (sql.length() > 0) {
						sql.append((char)c);
					}
				}
				else if (c == ';') {
					Strings.removeEnd(sql);
					if (sql.length() > 0) {
						return true;
					}
				}
				else {
					sql.append((char)c);
				}
			}
		}
		catch (IOException ioe) {
			close();
			throw new IllegalStateException(ioe);
		}

		Strings.removeEnd(sql);
		return sql.length() > 0;
	}

	/**
	 * Returns the next line in the wrapped Reader.
	 * 
	 * @return the next line from the input
	 * @throws NoSuchElementException if there is no line to return
	 */
	public String next() {
		return nextLine();
	}

	/**
	 * Returns the next line in the wrapped Reader.
	 * 
	 * @return the next line from the input
	 * @throws NoSuchElementException if there is no line to return
	 */
	public String nextLine() {
		if (!hasNext()) {
			throw new NoSuchElementException("No more lines");
		}

		try {
			return sql.toString();
		}
		finally {
			sql.setLength(0);
		}
	}

	/**
	 * Closes the underlying Reader quietly. This method is useful if you only want to
	 * process the first few lines of a larger file. If you do not close the iterator then the
	 * Reader remains open. This method can safely be called multiple times.
	 */
	public void close() {
		eof = true;
		sql.setLength(0);
		Streams.safeClose(reader);
	}

	/**
	 * Unsupported.
	 * 
	 * @throws UnsupportedOperationException always
	 */
	public void remove() {
		throw Exceptions.unsupported("Remove unsupported on LineIterator");
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy