| | +package com.whitemagicsoftware.rxm.tree.xml; |
| | + |
| | +import com.whitemagicsoftware.rxm.grammar.QueryBaseListener; |
| | +import com.whitemagicsoftware.rxm.grammar.QueryParser; |
| | + |
| | +import com.whitemagicsoftware.rxm.tree.Payload; |
| | +import com.whitemagicsoftware.rxm.tree.Tree; |
| | + |
| | +import org.antlr.v4.runtime.ParserRuleContext; |
| | + |
| | +/** |
| | + */ |
| | +public class SelectClause extends Clause { |
| | + /** Current context. */ |
| | + private Tree<Payload> selectClauseTree; |
| | + |
| | + /** |
| | + * Default constructor. |
| | + */ |
| | + public SelectClause() { |
| | + } |
| | + |
| | + /** |
| | + * Adds the root context node to the top-most part of the tree. This |
| | + * sets the context tree to the root context node. |
| | + * |
| | + * @param ctx The payload to transform. |
| | + */ |
| | + @Override |
| | + public synchronized void enterRoot( QueryParser.RootContext ctx ) { |
| | + setSelectClauseTree( createSelectClauseTree( ctx ) ); |
| | + } |
| | + |
| | + /** |
| | + * Invoked when parsing <b><code>table > path</code></b>. Adds a new |
| | + * leaf to the context tree, then changes the context tree to the newly |
| | + * added leaf. |
| | + * |
| | + * @param ctx The payload to transform. |
| | + */ |
| | + @Override |
| | + public synchronized void enterTableMap( QueryParser.TableMapContext ctx ) { |
| | + setSelectClauseTree( addLeaf( ctx ) ); |
| | + } |
| | + |
| | + /** |
| | + * Invoked when parsing <b><code>column > path</code></b>. Adds a new |
| | + * leaf to the context tree. |
| | + * |
| | + * @param ctx The payload to transform. |
| | + */ |
| | + @Override |
| | + public synchronized void enterColumnMap( QueryParser.ColumnMapContext ctx ) { |
| | + addLeaf( ctx ); |
| | + } |
| | + |
| | + /** |
| | + * Invoked when parsing <b><code>column > attribute</code></b>. Adds |
| | + * a new leaf to the context tree. |
| | + * |
| | + * @param ctx The payload to transform. |
| | + */ |
| | + @Override |
| | + public synchronized void enterAttributeMap( |
| | + QueryParser.AttributeMapContext ctx ) { |
| | + addLeaf( ctx ); |
| | + } |
| | + |
| | + /** |
| | + * Invoked when parsing <b><code>^</code></b>. Changes context tree to |
| | + * its parent. If the parent doesn't exist, this will fail silently. |
| | + * |
| | + * @param ctx Indicates that context should switch, has no payload. |
| | + */ |
| | + @Override |
| | + public synchronized void enterPop( QueryParser.PopContext ctx ) { |
| | + Tree<Payload> parent = getSelectClauseTree().getParent(); |
| | + |
| | + if( parent != null ) { |
| | + setSelectClauseTree( parent ); |
| | + } |
| | + } |
| | + |
| | + public String getFromClause() { |
| | + return ((SelectClauseTree<Payload>)getSelectClauseTree()).getFromClause(); |
| | + } |
| | + |
| | + /** |
| | + * Adds the given parser rule context to the current context tree. |
| | + * |
| | + * @param ctx The parser rule context to add as a leaf to the context tree. |
| | + * @return The leaf (tree) that was added. |
| | + */ |
| | + private Tree<Payload> addLeaf( ParserRuleContext ctx ) { |
| | + return getSelectClauseTree().addLeaf( createSelectClauseTree( ctx ) ); |
| | + } |
| | + |
| | + /** |
| | + * Changes where the next mapped items will be attached. |
| | + */ |
| | + private void setSelectClauseTree( Tree<Payload> selectClauseTree ) { |
| | + this.selectClauseTree = selectClauseTree; |
| | + } |
| | + |
| | + /** |
| | + * Returns where to attach upcoming map items. |
| | + */ |
| | + private Tree<Payload> getSelectClauseTree() { |
| | + return this.selectClauseTree; |
| | + } |
| | + |
| | + /** |
| | + * Creates a new tree with the given parser rule context. This is required |
| | + * so that the *Context classes are aware of their relative position in the |
| | + * hierarchy. As a consequence of that knowledge, the objects have access |
| | + * to the nearest table name, whether siblings exist, etc. |
| | + * |
| | + * @param ctx The context to wrap in a payload that is added to a tree. |
| | + * |
| | + * @return The tree that contains the payload that wraps the context. |
| | + */ |
| | + private Tree<Payload> createSelectClauseTree( ParserRuleContext ctx ) { |
| | + Tree<Payload> tree = getSelectClauseTree(); |
| | + Payload payload = new Payload( ctx ); |
| | + SelectClauseTree<Payload> sct = new SelectClauseTree<Payload>( payload ); |
| | + |
| | + // Ensure that the first payload (root node) has a valid payload tree. |
| | + payload.setTree( tree == null ? sct : tree ); |
| | + |
| | + return sct; |
| | + } |
| | + |
| | + /** |
| | + * This should only be called after the SELECT clause has been |
| | + * constructed using the AST. |
| | + * |
| | + * @return The SELECT portion of a SQL statement. |
| | + */ |
| | + public String toString() { |
| | + return getSelectClauseTree().getRoot().toString(); |
| | + } |
| | +} |
| | + |
| | |