/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.query.ui.sqleditor.component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.swing.text.html.Option;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.query.IQueryService;
import org.teiid.designer.query.sql.ICommandCollectorVisitor;
import org.teiid.designer.query.sql.lang.ICriteria;
import org.teiid.designer.query.sql.lang.IDelete;
import org.teiid.designer.query.sql.lang.IExistsCriteria;
import org.teiid.designer.query.sql.lang.IFrom;
import org.teiid.designer.query.sql.lang.IGroupBy;
import org.teiid.designer.query.sql.lang.IInsert;
import org.teiid.designer.query.sql.lang.ILanguageObject;
import org.teiid.designer.query.sql.lang.IOrderBy;
import org.teiid.designer.query.sql.lang.IQuery;
import org.teiid.designer.query.sql.lang.ISelect;
import org.teiid.designer.query.sql.lang.ISetQuery;
import org.teiid.designer.query.sql.lang.IStoredProcedure;
import org.teiid.designer.query.sql.lang.ISubqueryCompareCriteria;
import org.teiid.designer.query.sql.lang.ISubqueryFromClause;
import org.teiid.designer.query.sql.lang.ISubquerySetCriteria;
import org.teiid.designer.query.sql.lang.IUpdate;
import org.teiid.designer.query.sql.proc.ICommandStatement;
import org.teiid.designer.query.sql.proc.ICreateProcedureCommand;
import org.teiid.designer.query.sql.symbol.IScalarSubquery;
/**
* This class provides the GroupSymbolFinder the knowledge to know where the cursor is at so it can make decisions about what
* group symbols to include in the builders.
*
* @since 8.0
*/
public class SqlIndexLocator {
public static final int UNKNOWN = -1;
public static final int QUERY = 10;
// private static final int SUBQUERY = 11;
public static final int SET_QUERY = 12;
public static final int SELECT = 20;
public static final int FROM = 21;
public static final int WHERE = 22;
public static final int SUBQUERY_FROM_CLAUSE = 23;
public static final int SCALAR_SUBQUERY = 24;
// private static final int SELECT_IN_EXISTS_CRITERIA = 25;
// private static final int SELECT_IN_UNION_SELECT = 26;
public static final int CRITERIA = 30;
public static final int EXISTS_CRITERIA = 31;
public static final int HAS_CRITERIA = 32;
public static final int SUBQUERY_COMPARE_CRITERIA = 33;
public static final int SUBQUERY_SET_CRITERIA = 34;
public static final int GROUP_BY = 40;
public static final int ORDER_BY = 41;
public static final int HAVING = 42;
public static final int OPTION = 43;
public static final int UPDATE = 50;
public static final int INSERT = 51;
public static final int DELETE = 52;
public static final int STORED_PROCEDURE = 53;
public static final int CREATE_UPDATE_PROCEDURE = 54;
public static final int COMMAND_STATEMENT = 60;
private static final int TYPE_UNKNOWN = -1;
private static final int TYPE_QUERY = 0;
// private static final int TYPE_SUBQUERY = 1;
private static final int TYPE_UNION = 2;
private static final int TYPE_QUERY_IN_CRITERIA = 3;
private static final int TYPE_QUERY_IN_UNION = 4;
private static final int TYPE_QUERY_IN_COMMAND = 5;
// private static final String UNKNOWN_STR = "Unknown Node"; //$NON-NLS-1$
//
// private static final String QUERY_STR = "Query Node"; //$NON-NLS-1$
//// private static final String SUBQUERY_STR = "Subquery Node"; //$NON-NLS-1$
// private static final String SET_QUERY_STR = "Set Query Node"; //$NON-NLS-1$
//
// private static final String SELECT_STR = "Select Node"; //$NON-NLS-1$
// private static final String FROM_STR = "From Node"; //$NON-NLS-1$
// private static final String WHERE_STR = "Where Node"; //$NON-NLS-1$
// private static final String SUBQUERY_FROM_CLAUSE_STR = "Subquery From Clause Node"; //$NON-NLS-1$
// private static final String SCALAR_SUBQUERY_STR = "Scalar Subquery Node"; //$NON-NLS-1$
//// private static final String SELECT_IN_EXISTS_CRITERIA_STR = "Select Node in Exists Criteria Node"; //$NON-NLS-1$
//// private static final String SELECT_IN_UNION_SELECT_STR = "Select Node in Union Node"; //$NON-NLS-1$
//
//
// private static final String CRITERIA_STR = "Critiera Node"; //$NON-NLS-1$
// private static final String EXISTS_CRITERIA_STR = "Exists Criteria Node"; //$NON-NLS-1$
// private static final String HAS_CRITERIA_STR = "Has Criteria Node"; //$NON-NLS-1$
// private static final String SUBQUERY_COMPARE_CRITERIA_STR = "Subquery Compare Criteria Node"; //$NON-NLS-1$
// private static final String SUBQUERY_SET_CRITERIA_STR = "Subquery Set Criteria Node"; //$NON-NLS-1$
//
// private static final String GROUP_BY_STR = "Group By Node"; //$NON-NLS-1$
// private static final String ORDER_BY_STR = "Order By Node"; //$NON-NLS-1$
// private static final String HAVING_STR = "Having Node"; //$NON-NLS-1$
// private static final String OPTION_STR = "Option Node"; //$NON-NLS-1$
//
// private static final String UPDATE_STR = "Update Node"; //$NON-NLS-1$
// private static final String INSERT_STR = "Insert Node"; //$NON-NLS-1$
// private static final String DELETE_STR = "Delete Node"; //$NON-NLS-1$
// private static final String STORED_PROCEDURE_STR = "Stored Procedure Node"; //$NON-NLS-1$
// private static final String CREATE_UPDATE_PROCEDURE_STR = "Create Update Procedure Node"; //$NON-NLS-1$
//
// private static final String COMMAND_STATEMENT_STR = "Command Statement Node"; //$NON-NLS-1$
// private static final String IN = " In "; //$NON-NLS-1$
private int currentIndex = 0;
private int primaryNodeType = UNKNOWN;
private int primaryLanguageObjectType = TYPE_UNKNOWN;
private QueryDisplayComponent displayComponent;
private DisplayNode commandDisplayNode;
private DisplayNode primaryIndexDisplayNode;
private ILanguageObject primaryLanguageObject;
// private String primaryLOTypeString = null;
private boolean subQuerySelected = false;
private boolean selectScopeSelected = false;
private boolean whereSelected = false;
/**
* Constructor
*
* @since 4.2
*/
public SqlIndexLocator( QueryDisplayComponent displayComponent,
int index ) {
super();
this.displayComponent = displayComponent;
init(index);
}
public boolean isSubQuerySelected() {
return subQuerySelected;
}
public boolean isUnionSegmentSelected() {
return primaryLanguageObjectType == TYPE_QUERY_IN_UNION;
}
public boolean isCriteriaQuerySelected() {
return primaryLanguageObjectType == TYPE_QUERY_IN_CRITERIA || getDisplayNodeType(primaryIndexDisplayNode) == WHERE;
}
public boolean isCommandQuerySelected() {
return primaryLanguageObjectType == TYPE_QUERY_IN_COMMAND;
}
public boolean hasSubQueries() {
if (primaryLanguageObject != null && primaryLanguageObject instanceof IQuery) {
IQueryService queryService = ModelerCore.getTeiidQueryService();
ICommandCollectorVisitor commandCollectorVisitor = queryService.getCommandCollectorVisitor();
List subCommands = commandCollectorVisitor.findCommands((IQuery)primaryLanguageObject);
return !subCommands.isEmpty();
}
return false;
}
private void init( int index ) {
if (index < 0) currentIndex = 0;
else this.currentIndex = index;
commandDisplayNode = displayComponent.getCommandDisplayNodeAtIndex(currentIndex);
if (commandDisplayNode == null) // carretOffset too large??
commandDisplayNode = displayComponent.getDisplayNode();
// correctIndexForCommandDisplayNode();
primaryLanguageObject = commandDisplayNode.getLanguageObject();
setPrimaryIndexDisplayNode();
setPrimaryLanguageObjectType();
// System.out.println("\n " + getScopeDescription()); //$NON-NLS-1$
// System.out.println(" FULL = " + getFullScopeDescription(getScopeDescription()));
selectScopeSelected = isIndexInSelectScope();
subQuerySelected = isSubQueryNode(commandDisplayNode);
whereSelected = isIndexInWhere();
}
private void setPrimaryLanguageObjectType() {
if (primaryLanguageObject != null) {
if (primaryLanguageObject instanceof IQuery) {
// Check to see if it's a subquery???
DisplayNode parentNode = commandDisplayNode.getParent();
if (parentNode != null && getDisplayNodeType(parentNode) == EXISTS_CRITERIA) {
primaryLanguageObjectType = TYPE_QUERY_IN_CRITERIA;
// primaryLOTypeString = "QUERY in CRITERIA"; //$NON-NLS-1$
} else if (parentNode != null && getDisplayNodeType(parentNode) == SET_QUERY) {
primaryLanguageObjectType = TYPE_QUERY_IN_UNION;
// primaryLOTypeString = "QUERY in UNION"; //$NON-NLS-1$
} else if (parentNode != null && getDisplayNodeType(parentNode) == COMMAND_STATEMENT) {
primaryLanguageObjectType = TYPE_QUERY_IN_COMMAND;
// primaryLOTypeString = "QUERY in COMMAND"; //$NON-NLS-1$
} else {
primaryLanguageObjectType = TYPE_QUERY;
// primaryLOTypeString = "QUERY"; //$NON-NLS-1$
}
} else if (primaryLanguageObject instanceof ISetQuery) {
DisplayNode parentNode = commandDisplayNode.getParent();
if (parentNode != null && getDisplayNodeType(parentNode) == EXISTS_CRITERIA) {
primaryLanguageObjectType = TYPE_QUERY_IN_CRITERIA;
// primaryLOTypeString = "UNION QUERY IN CRITERIA"; //$NON-NLS-1$
} else if (parentNode != null && getDisplayNodeType(parentNode) == SET_QUERY) {
primaryLanguageObjectType = TYPE_QUERY_IN_UNION;
// primaryLOTypeString = "UNION QUERY IN UNION"; //$NON-NLS-1$
} else if (parentNode != null && getDisplayNodeType(parentNode) == SUBQUERY_FROM_CLAUSE) {
primaryLanguageObjectType = TYPE_QUERY_IN_UNION;
// primaryLOTypeString = "UNION QUERY IN SUBQUERY FROM"; //$NON-NLS-1$
} else {
primaryLanguageObjectType = TYPE_UNION;
// primaryLOTypeString = "UNION"; //$NON-NLS-1$
}
} else {
primaryLanguageObjectType = TYPE_UNKNOWN;
}
}
}
private void setPrimaryIndexDisplayNode() {
// Need take the display node and check the index to see if it's between the first SELECT
// first FROM\
int lastEndIndex = -1;
DisplayNode lastNode = null;
if (commandDisplayNode != null) {
List displayNodes = commandDisplayNode.getChildren();
lastNode = commandDisplayNode;
Iterator iter = displayNodes.iterator();
while (iter.hasNext()) {
DisplayNode node = (DisplayNode)iter.next();
lastEndIndex = node.endIndex;
if (currentIndex >= node.startIndex && currentIndex <= node.endIndex) {
primaryIndexDisplayNode = node;
setPrimaryIndexNodeType();
break;
} else if (currentIndex < lastEndIndex) {
primaryIndexDisplayNode = lastNode;
setPrimaryIndexNodeType();
}
lastNode = node;
}
if (primaryIndexDisplayNode == null) {
primaryIndexDisplayNode = lastNode;
setPrimaryIndexNodeType();
}
}
}
private void setPrimaryIndexNodeType() {
primaryNodeType = getDisplayNodeType(primaryIndexDisplayNode);
}
public int getDisplayNodeType( DisplayNode node ) {
if (node == null) {
return UNKNOWN;
}
if (node.languageObject instanceof ISelect) {
return SELECT;
} else if (node.languageObject instanceof IFrom) {
return FROM;
} else if (node instanceof WhereDisplayNode) {
return WHERE;
} else if (node.languageObject instanceof IGroupBy) {
return GROUP_BY;
} else if (node instanceof HavingDisplayNode) {
return HAVING;
} else if (node.languageObject instanceof IOrderBy) {
return ORDER_BY;
} else if (node.languageObject instanceof Option) {
return OPTION;
} else if (node.languageObject instanceof IQuery) {
return QUERY;
} else if (node.languageObject instanceof ISetQuery) {
return SET_QUERY;
} else if (node.languageObject instanceof IUpdate) {
return UPDATE;
} else if (node.languageObject instanceof IInsert) {
return INSERT;
} else if (node.languageObject instanceof IDelete) {
return DELETE;
} else if (node.languageObject instanceof IStoredProcedure) {
return STORED_PROCEDURE;
} else if (node.languageObject instanceof ICreateProcedureCommand) {
return CREATE_UPDATE_PROCEDURE;
} else if (node.languageObject instanceof IExistsCriteria) {
return EXISTS_CRITERIA;
} else if (node.languageObject instanceof ISubqueryFromClause) {
return SUBQUERY_FROM_CLAUSE;
} else if (node.languageObject instanceof IScalarSubquery) {
return SCALAR_SUBQUERY;
} else if (node.languageObject instanceof ISubqueryCompareCriteria) {
return SUBQUERY_COMPARE_CRITERIA;
} else if (node.languageObject instanceof ISubquerySetCriteria) {
return SUBQUERY_SET_CRITERIA;
} else if (node.languageObject instanceof ICriteria) {
return CRITERIA;
} else if (node.languageObject instanceof ICommandStatement) {
return COMMAND_STATEMENT;
} else {
return UNKNOWN;
}
}
public ILanguageObject getPrimaryLanguageObject() {
return this.primaryLanguageObject;
}
public int getPrimaryNodeType() {
return this.primaryNodeType;
}
public boolean isSubQueryNode( DisplayNode node ) {
int nodeType = getDisplayNodeType(node);
if (nodeType == QUERY || nodeType == SET_QUERY) {
// Check it's parent's parent. if FROM, then subquery
DisplayNode parentNode = node.getParent();
if (parentNode != null) {
int parentType = getDisplayNodeType(parentNode);
if (parentType == SUBQUERY_FROM_CLAUSE) return true;
if (parentType == SET_QUERY && primaryLanguageObjectType == TYPE_QUERY_IN_UNION) {
parentNode = parentNode.getParent();
if (parentNode != null) {
if (getDisplayNodeType(parentNode) == SUBQUERY_FROM_CLAUSE) return true;
}
}
}
}
return false;
}
public int getIndexForDisplayNode( DisplayNode parentNode,
DisplayNode targetNode ) {
if (targetNode.getParent() != null && !parentNode.getChildren().isEmpty()) {
// Walk through the children
Iterator iter = parentNode.getChildren().iterator();
DisplayNode nextNode = null;
while (iter.hasNext()) {
nextNode = (DisplayNode)iter.next();
if (nextNode.equals(targetNode)) {
return nextNode.startIndex;
}
int tmpIndex = getIndexForDisplayNode(nextNode, targetNode);
if (tmpIndex > -1) return tmpIndex;
}
}
return -1;
}
public DisplayNode getTopDisplayNode() {
DisplayNode parentNode = commandDisplayNode;
while (parentNode.getParent() != null) {
parentNode = parentNode.getParent();
}
return parentNode;
}
public DisplayNode getCommandDisplayNode() {
return this.commandDisplayNode;
}
public int getCurrentIndex() {
return this.currentIndex;
}
public boolean isIndexInSelectScope() {
// Need take the display node and check the index to see if it's between the first SELECT
// first FROM\
if (primaryIndexDisplayNode instanceof SelectDisplayNode || primaryIndexDisplayNode instanceof FromDisplayNode) return true;
int startSelectIndex = -1;
int endFromIndex = -1;
List displayNodes = primaryIndexDisplayNode.getChildren();
Iterator iter = displayNodes.iterator();
while (iter.hasNext()) {
DisplayNode node = (DisplayNode)iter.next();
if (node.languageObject instanceof ISelect) {
startSelectIndex = node.startIndex;
}
if (node.languageObject instanceof IFrom) {
endFromIndex = node.endIndex + 1;
}
int correctedIndex = getCurrentIndex() - getCommandDisplayNode().getStartIndex();
if (node instanceof WhereDisplayNode) {
boolean inNode = isIndexInSelectScope(node, correctedIndex);
if (inNode) return true;
}
if (node.languageObject instanceof IExistsCriteria) {
boolean inNode = false;
for (Iterator iter2 = node.getChildren().iterator(); iter2.hasNext();) {
DisplayNode nextNode = (DisplayNode)iter2.next();
inNode = isIndexInSelectScope(nextNode, currentIndex);
if (inNode) return true;
}
}
if (startSelectIndex > -1 && endFromIndex > -1) {
if (currentIndex >= startSelectIndex && currentIndex <= endFromIndex) return true;
return false;
}
}
return false;
}
private boolean isIndexInSelectScope( DisplayNode displayNode,
int index ) {
// Need take the display node and check the index to see if it's between the first SELECT
// first FROM\
if (displayNode != null) {
if (displayNode.languageObject instanceof ISelect || displayNode.languageObject instanceof IFrom) return true;
int startSelectIndex = -1;
int endFromIndex = -1;
List displayNodes = displayNode.getChildren();
Iterator iter = displayNodes.iterator();
while (iter.hasNext()) {
DisplayNode node = (DisplayNode)iter.next();
if (node.languageObject instanceof ISelect) {
startSelectIndex = node.startIndex;
}
if (node.languageObject instanceof IFrom) {
endFromIndex = node.endIndex + 1;
}
if (node instanceof WhereDisplayNode || node.languageObject instanceof IExistsCriteria
|| node.languageObject instanceof IQuery) {
boolean inNode = isIndexInSelectScope(node, index);
if (inNode) return true;
}
if (startSelectIndex > -1 && endFromIndex > -1) {
if (index >= startSelectIndex && index <= endFromIndex) return true;
}
}
}
return false;
}
public boolean isIndexInWhere() {
// Need take the display node and check the index to see if it's within a WHERE clause
if (primaryIndexDisplayNode instanceof WhereDisplayNode) return true;
List displayNodes = primaryIndexDisplayNode.getChildren();
Iterator iter = displayNodes.iterator();
while (iter.hasNext()) {
DisplayNode node = (DisplayNode)iter.next();
int correctedIndex = getCurrentIndex() - getCommandDisplayNode().getStartIndex();
if (node instanceof WhereDisplayNode) {
if (correctedIndex >= node.startIndex && correctedIndex <= node.endIndex) return true;
}
}
return false;
}
public boolean isWhereSelected() {
return this.whereSelected;
}
public boolean isSelectScopeSelected() {
return this.selectScopeSelected;
}
public DisplayNode getSelectedSelectQuery() {
if (primaryIndexDisplayNode.languageObject instanceof ISelect || primaryIndexDisplayNode.languageObject instanceof IFrom) return primaryIndexDisplayNode.getParent();
int startSelectIndex = -1;
int endFromIndex = -1;
List displayNodes = primaryIndexDisplayNode.getChildren();
Iterator iter = displayNodes.iterator();
while (iter.hasNext()) {
DisplayNode node = (DisplayNode)iter.next();
if (node instanceof SelectDisplayNode) {
startSelectIndex = node.startIndex;
}
if (node.languageObject instanceof IFrom) {
endFromIndex = node.endIndex + 1;
}
int correctedIndex = getCurrentIndex() - getCommandDisplayNode().getStartIndex();
if (node instanceof WhereDisplayNode) {
DisplayNode selectNode = getSelectedSelectQuery(node, correctedIndex);
if (selectNode != null) return selectNode;
}
if (node.languageObject instanceof IExistsCriteria) {
for (Iterator iter2 = node.getChildren().iterator(); iter2.hasNext();) {
DisplayNode nextNode = (DisplayNode)iter2.next();
DisplayNode selectNode = getSelectedSelectQuery(nextNode, currentIndex);
if (selectNode != null) return selectNode;
}
}
if (startSelectIndex > -1 && endFromIndex > -1) {
if (currentIndex >= startSelectIndex && currentIndex <= endFromIndex) return node.getParent();
return null;
}
}
return null;
}
private DisplayNode getSelectedSelectQuery( DisplayNode displayNode,
int index ) {
// Need take the display node and check the index to see if it's between the first SELECT
// last FROM indexes
if (displayNode != null) {
if (displayNode.languageObject instanceof ISelect || displayNode.languageObject instanceof IFrom) return displayNode.getParent();
int startSelectIndex = -1;
int endFromIndex = -1;
List displayNodes = displayNode.getChildren();
Iterator iter = displayNodes.iterator();
while (iter.hasNext()) {
DisplayNode node = (DisplayNode)iter.next();
if (node.languageObject instanceof ISelect) {
startSelectIndex = node.startIndex;
}
if (node.languageObject instanceof IFrom) {
endFromIndex = node.endIndex + 1;
}
if (node instanceof WhereDisplayNode || node.languageObject instanceof IExistsCriteria
|| node.languageObject instanceof IQuery) {
DisplayNode selectNode = getSelectedSelectQuery(node, index);
if (selectNode != null) return selectNode;
}
if (startSelectIndex > -1 && endFromIndex > -1) {
if (currentIndex >= startSelectIndex && currentIndex <= endFromIndex) return node.getParent();
}
}
}
return null;
}
public List collectCriteriaParentQueries( boolean useSelectQuery ) {
if (isCriteriaQuerySelected()) {
// Let's get selection starting point
DisplayNode startingNode = null;
if (useSelectQuery) startingNode = getSelectedSelectQuery();
else startingNode = primaryIndexDisplayNode;
// From the current primaryIndexDisplayNode, walk up and find all nested Criteria parents
List parentQueries = new ArrayList();
parentQueries.add(startingNode);
boolean foundUnexpectedParent = false;
boolean shouldFindCriteria = false;
boolean foundExpectedCriteria = true;
DisplayNode parentNode = startingNode.getParent();
while (!foundUnexpectedParent && foundExpectedCriteria) {
if (parentNode == null) foundUnexpectedParent = true;
else {
if (shouldFindCriteria && !(parentNode.languageObject instanceof IExistsCriteria)) foundExpectedCriteria = false;
if (foundExpectedCriteria) {
shouldFindCriteria = false;
if (parentNode.languageObject instanceof IQuery) {
parentQueries.add(parentNode);
// Expect to find another exists criteria next
if (parentNode.getParent() != null
&& !(parentNode.getParent().languageObject instanceof ISubqueryFromClause)) {
shouldFindCriteria = true;
}
} else if (parentNode.languageObject instanceof IFrom || parentNode.languageObject instanceof ISelect
|| parentNode.languageObject instanceof IExistsCriteria || parentNode instanceof WhereDisplayNode
|| parentNode.languageObject instanceof ISubqueryFromClause) {
// ALL OK
} else {
foundUnexpectedParent = true;
}
}
parentNode = parentNode.getParent();
}
}
return parentQueries;
}
return Collections.EMPTY_LIST;
}
public boolean isSelectedNodeContainedWithinType( int type ) {
// Need to walk the display node and check parents until done
DisplayNode parentNode = primaryIndexDisplayNode;
while (parentNode != null) {
if (getDisplayNodeType(parentNode) == type) {
return true;
}
parentNode = parentNode.getParent();
}
return false;
}
public DisplayNode getExistsCriteriaWhereNode( DisplayNode node ) {
DisplayNode whereNode = node.getParent();
if (whereNode != null && getDisplayNodeType(whereNode) == SqlIndexLocator.WHERE) {
DisplayNode queryNode = whereNode.getParent();
if (queryNode != null && queryNode.languageObject instanceof IQuery) {
return queryNode;
}
}
return null;
}
}