package hiro.yoshioka.ast.sql;

import hiro.yoshioka.ast.sql.util.ASTAssist;
import hiro.yoshioka.sql.resource.DBRoot;
import hiro.yoshioka.sql.resource.IDBTable;
import hiro.yoshioka.util.StringUtil;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class AbsSQLParser {
	public static IParserException _INTERNAL_EXCEPTION;
	protected Log fLogger = LogFactory.getLog(this.getClass());
	protected int lastDML = 0;
	protected ASTAssist fAssist;
	protected DBRoot fDBRoot;
	protected boolean fOpen;
	private Map<String, Set<String>> tableAliasSetMap;

	protected boolean hasDBRoot() {
		return this.fDBRoot != null;
	}

	public boolean parse(DBRoot root) {
		this.fDBRoot = root;
		return parse();
	}

	public boolean hasTableAliasSet(String tableName) {
		if (tableAliasSetMap == null) {
			return false;
		}
		Set<String> aliasSet = tableAliasSetMap.get(tableName.toUpperCase());
		if (aliasSet == null) {
			return false;
		}
		return true;
	}

	public String getFirstTableAlias(IDBTable table) {
		if (hasTableAliasSet(table.getName())) {
			Set<String> set = getTableAliasSet(table.getName());
			return set.iterator().next();
		} else {
			return StringUtil.EMPTY_STRING;
		}
	}

	public Set<String> getTableAliasSet(IDBTable table) {
		return getTableAliasSet(table.getName());
	}

	public Set<String> getTableAliasSet(String tableName) {
		if (tableAliasSetMap == null) {
			return Collections.EMPTY_SET;
		}
		Set<String> aliasSet = tableAliasSetMap.get(tableName.toUpperCase());
		if (aliasSet == null) {
			return Collections.EMPTY_SET;
		}
		return aliasSet;
	}

	public void addTableAlias(IDBTable table, String alias) {
		if (tableAliasSetMap == null) {
			tableAliasSetMap = new HashMap<String, Set<String>>();
		}
		Set<String> aliasSet = tableAliasSetMap.get(table.getUName());
		if (aliasSet == null) {
			aliasSet = new LinkedHashSet<String>();
			tableAliasSetMap.put(table.getUName(), aliasSet);
		}
		aliasSet.add(alias);
	}

	public abstract boolean parse();

	public boolean hasException() {
		return _INTERNAL_EXCEPTION != null;
	}

	public IParserException getException() {
		return _INTERNAL_EXCEPTION;
	}

	public Iterator getExpectedTokens() {
		return _INTERNAL_EXCEPTION.getExpectedTokenIterator();
	}

	public abstract AbsSimpleNode getRoot();

	public abstract boolean nodeCreated();

	protected void open() {
		this.fOpen = true;
	}

	protected void close() {
		this.fOpen = false;
	}

	protected String printToken(IToken t) {
		return "This Token [" + t.getImage() + "] [" + t.getBeginLine() + "/"
				+ t.getBeginColumn() + "]";
	}

	public abstract void enable_tracing();

	public abstract void disable_tracing();

}
