/* * 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 org.teiid.designer.core.ModelerCore; import org.teiid.designer.query.IQueryService; import org.teiid.designer.query.sql.ISQLConstants; import org.teiid.designer.query.sql.ISQLStringVisitor; import org.teiid.designer.query.sql.ISQLStringVisitorCallback; import org.teiid.designer.query.sql.lang.ICommand; import org.teiid.designer.query.sql.lang.ICriteria; import org.teiid.designer.query.sql.lang.ILanguageObject; import org.teiid.designer.query.sql.lang.ISubqueryContainer; import org.teiid.designer.query.sql.proc.IExpressionStatement; import org.teiid.designer.query.sql.symbol.IAggregateSymbol; import org.teiid.designer.query.sql.symbol.IExpressionSymbol; /** * This visitor works intimately with the SQLStringVisitor to construct a display node tree. */ public final class DisplayNodeVisitor implements ISQLStringVisitorCallback { private final DisplayNode node; private final boolean dontAppend; private int indentLevel; private int originalLevel; DisplayNodeVisitor(DisplayNode node, boolean dontAppend, int indentLevel) { this.node = node; this.dontAppend = dontAppend; this.indentLevel = indentLevel; this.originalLevel = indentLevel; } @Override public void visitNode(ILanguageObject obj) { if (obj == null) { append(DisplayNodeConstants.UNDEFINED); return; } if ((obj instanceof IExpressionSymbol && !(obj instanceof IAggregateSymbol))) { IQueryService queryService = ModelerCore.getTeiidQueryService(); ISQLStringVisitor delegate = queryService.getCallbackSQLStringVisitor(this); obj.acceptVisitor(delegate); return; } // turn off indenting for nested commands int childIndent = indentLevel; if ((node.languageObject instanceof ISubqueryContainer || node.languageObject instanceof IExpressionStatement) && obj instanceof ICommand) { childIndent = -1; } DisplayNode child = DisplayNodeFactory.createDisplayNode(node, obj, childIndent); node.addChildNode(child); } @Override public void addTabs(int level) { setIndentLevel(this.originalLevel + level); if (this.indentLevel > 0) { node.displayNodeList.addAll(DisplayNodeUtils.getIndentNodes(node, this.indentLevel)); } } @Override public void visitCriteria(String keyWord, ICriteria crit) { if (ISQLConstants.WHERE.equals(keyWord)) { DisplayNode child = new WhereDisplayNode(node, crit); createCriteriaNode(keyWord, crit, child); } else if (ISQLConstants.HAVING.equals(keyWord)) { DisplayNode child = new HavingDisplayNode(node, crit); createCriteriaNode(keyWord, crit, child); } else { append(keyWord); append(DisplayNodeConstants.SPACE); visitNode(crit); } } private void createCriteriaNode(String keyWord, ICriteria crit, DisplayNode child) { node.addChildNode(child); child.displayNodeList.add(DisplayNodeFactory.createDisplayNode(child, keyWord)); setIndentLevel(this.indentLevel + 1); beginClause(child, this.indentLevel); child.addChildNode(DisplayNodeFactory.createDisplayNode(child, crit, indentLevel)); } @Override public void append(Object value) { if (dontAppend) { return; // for compatibility, this keeps symbols from having children } // otherwise, the value is a string/enum/primitive node.displayNodeList.add(DisplayNodeFactory.constructDisplayNode(node, value)); } @Override public void beginClause(int level) { setIndentLevel(this.originalLevel + level); beginClause(node, this.indentLevel); } private void beginClause(DisplayNode node, int level) { if (level >= 0 && DisplayNodeUtils.isClauseCROn()) { node.displayNodeList.add(DisplayNodeFactory.createDisplayNode(node, DisplayNodeConstants.CR)); if (DisplayNodeUtils.isClauseIndentOn()) { node.displayNodeList.addAll(DisplayNodeUtils.getIndentNodes(node, level)); } } else { node.displayNodeList.add(DisplayNodeFactory.createDisplayNode(node, DisplayNodeConstants.SPACE)); } } private void setIndentLevel(int indentLevel) { // preserve -1, which means no indenting if (this.indentLevel != -1) { this.indentLevel = indentLevel; } } }