| Author | Dave Jarvis <email> |
|---|---|
| Date | 2015-03-25 22:36:47 GMT-0700 |
| Commit | b992d7dff8bd46ca666a29394e2bb81f7ec05ce3 |
| Parent | e594cd5 |
| # Overview | ||
| -Relational eXpression Map (**rxm**) is a database- and output-agnostic query | ||
| -language for generating structured documents. | ||
| +Relational eXpression Map (**rxm**) is a database- and output-agnostic | ||
| +query language for generating structured documents. | ||
| # Requirements |
| } | ||
| - public void hasPrecedingPayload( boolean hasPrecedingPayload ) { | ||
| - this.hasPrecedingPayload = hasPrecedingPayload; | ||
| - } | ||
| - | ||
| - public void hasFollowingPayload( boolean hasFollowingPayload ) { | ||
| - this.hasFollowingPayload = hasFollowingPayload; | ||
| - } | ||
| - | ||
| /** | ||
| * Opens the XMLATTRIBUTES expression. | ||
| * | ||
| * @return Token containing ",XMLATTRIBUTES(" ... | ||
| */ | ||
| - @Override | ||
| - public Token getStart() { | ||
| + public String getStart() { | ||
| String | ||
| tableName = getParentTableName(), | ||
| columnName = getColumnText(), | ||
| attributeName = getAttributeText(); | ||
| - return new Token( | ||
| - String.format( ",%s", hasPrecedingPayload() ? | ||
| - nextAttribute( tableName, columnName, attributeName ) : | ||
| - firstAttribute( tableName, columnName, attributeName ) | ||
| - ) | ||
| + return String.format( ",%s", hasPrecedingPayload() ? | ||
| + nextAttribute( tableName, columnName, attributeName ) : | ||
| + firstAttribute( tableName, columnName, attributeName ) | ||
| ); | ||
| - } | ||
| - | ||
| - private boolean hasPrecedingPayload() { | ||
| - return this.hasPrecedingPayload; | ||
| - } | ||
| - | ||
| - private boolean hasFollowingPayload() { | ||
| - return this.hasFollowingPayload; | ||
| } | ||
| /** | ||
| * Closes the XMLATTRIBUTES expression, should no more attributes be | ||
| * forthcoming. | ||
| * | ||
| * @return Token containing ")" or the empty string. | ||
| */ | ||
| - @Override | ||
| - public Token getStop() { | ||
| - return new Token( hasFollowingPayload() ? "" : ")" ); | ||
| + public String getStop() { | ||
| + return hasFollowingPayload() ? "" : ")"; | ||
| } | ||
| return result; | ||
| + } | ||
| + | ||
| + public void hasPrecedingPayload( boolean hasPrecedingPayload ) { | ||
| + this.hasPrecedingPayload = hasPrecedingPayload; | ||
| + } | ||
| + | ||
| + public void hasFollowingPayload( boolean hasFollowingPayload ) { | ||
| + this.hasFollowingPayload = hasFollowingPayload; | ||
| + } | ||
| + | ||
| + private boolean hasPrecedingPayload() { | ||
| + return this.hasPrecedingPayload; | ||
| + } | ||
| + | ||
| + private boolean hasFollowingPayload() { | ||
| + return this.hasFollowingPayload; | ||
| } | ||
| } | ||
| * @return ",XMLELEMENT(" ...* | ||
| */ | ||
| - @Override | ||
| - public Token getStart() { | ||
| - return new Token( | ||
| - String.format( ",%s,%s.%s", | ||
| - startElement( path() ), | ||
| - getParentTableName(), | ||
| - getColumnText() | ||
| - ) | ||
| + public String getStart() { | ||
| + return String.format( ",%s,%s.%s", | ||
| + startElement( path() ), | ||
| + getParentTableName(), | ||
| + getColumnText() | ||
| ); | ||
| } | ||
| - @Override | ||
| - public Token getStop() { | ||
| - return new Token( | ||
| - String.format( "%s%s", | ||
| - stopElement( path() ), | ||
| - super.getStop().toString() | ||
| - ) | ||
| + public String getStop() { | ||
| + return String.format( "%s%s", | ||
| + stopElement( path() ), | ||
| + super.getStop().toString() | ||
| ); | ||
| } |
| * Represents a wrapper class for ParserRuleContext. | ||
| */ | ||
| -public abstract class Context extends ParserRuleContext { | ||
| +public abstract class Context { | ||
| private ParserRuleContext parserRuleContext; | ||
| * @return "(" | ||
| */ | ||
| - @Override | ||
| - public Token getStart() { | ||
| - return new Token( "(" ); | ||
| + public String getStart() { | ||
| + return "("; | ||
| } | ||
| /** | ||
| * Closes the current transformation expression. Subclasses may override | ||
| * this to provide a custom closing SQL/XML expression. | ||
| * | ||
| * @return ")" | ||
| */ | ||
| - @Override | ||
| - public Token getStop() { | ||
| - return new Token( ")" ); | ||
| + public String getStop() { | ||
| + return ")"; | ||
| } | ||
| * @return "SELECT XMLROOT(" ... + ",XMLELEMENT(" ... | ||
| */ | ||
| - @Override | ||
| - public Token getStart() { | ||
| + public String getStart() { | ||
| QueryParser.ElementContext element = getElementContext(); | ||
| String e = element.getText(); | ||
| - String s = String.format( "XMLROOT(%s", startElement( e ) ); | ||
| - return new Token( s ); | ||
| + return String.format( "XMLROOT(%s", startElement( e ) ); | ||
| } | ||
| /** | ||
| * Closes the XMLELEMENT and XMLROOT. | ||
| */ | ||
| - @Override | ||
| - public Token getStop() { | ||
| - return new Token( String.format( ")%s)", getDeclaration() ) ); | ||
| + public String getStop() { | ||
| + return String.format( ")%s)", getDeclaration() ); | ||
| } | ||
| public class SelectClause extends Clause { | ||
| - private Tree<ParserRuleContext> tree; | ||
| + private Tree<Context> tree; | ||
| /** | ||
| @Override | ||
| public void enterPop( QueryParser.PopContext ctx ) { | ||
| - Tree<ParserRuleContext> parent = getTree().getParent(); | ||
| + Tree<Context> parent = getTree().getParent(); | ||
| if( parent != null ) { | ||
| * @return The leaf (tree) that was added. | ||
| */ | ||
| - private Tree<ParserRuleContext> addLeaf( ParserRuleContext ctx ) { | ||
| + private Tree<Context> addLeaf( Context ctx ) { | ||
| return getTree().addLeaf( createTree( ctx ) ); | ||
| } | ||
| /** | ||
| * Changes where the next mapped items will be attached. | ||
| */ | ||
| - private void setTree( Tree<ParserRuleContext> tree ) { | ||
| + private void setTree( Tree<Context> tree ) { | ||
| this.tree = tree; | ||
| } | ||
| /** | ||
| * Returns where to attach upcoming map items. | ||
| */ | ||
| - private Tree<ParserRuleContext> getTree() { | ||
| + private Tree<Context> getTree() { | ||
| return this.tree; | ||
| } | ||
| /** | ||
| * Creates a new tree with the given parser rule context. | ||
| * | ||
| * @param ctx The context to wrap in a payload that is added to a tree. | ||
| * @return A new tree with a single data element and no branches. | ||
| */ | ||
| - private Tree<ParserRuleContext> createTree( ParserRuleContext ctx ) { | ||
| + private Tree<Context> createTree( Context ctx ) { | ||
| return new SelectTree( ctx ); | ||
| } | ||
| private QueryParser.TableContext getParentTable() { | ||
| return ((QueryParser.TableMapContext)getParentParserRuleContext()).table(0); | ||
| } | ||
| private ParserRuleContext getParentParserRuleContext() { | ||
| - return ((TableMapContext)getTreePayload()).getParserRuleContext(); | ||
| + return getTreePayload().getParserRuleContext(); | ||
| } | ||
| private String getParentTableName() { | ||
| return getParentTable().getText(); | ||
| } | ||
| - private ParserRuleContext getTreePayload() { | ||
| + private Context getTreePayload() { | ||
| return getTree().getPayload(); | ||
| } | ||
| import com.whitemagicsoftware.rxm.Tree; | ||
| -import org.antlr.v4.runtime.ParserRuleContext; | ||
| import org.antlr.v4.runtime.Token; | ||
| /** | ||
| * This creates a tree capable of generating a SQL/XML SELECT clause. | ||
| */ | ||
| -public class SelectTree extends Tree<ParserRuleContext> { | ||
| +public class SelectTree extends Tree<Context> { | ||
| public static final int INDENT = 2; | ||
| /** | ||
| * Constructs a tree capable of transforming itself into a SQL/XML | ||
| * SELECT clause. | ||
| * | ||
| * @param payload The data associated with this tree leaf (must not | ||
| * be null). | ||
| */ | ||
| - public SelectTree( ParserRuleContext payload ) { | ||
| + public SelectTree( Context payload ) { | ||
| super( payload ); | ||
| } | ||
| * @return The fully transformed text. | ||
| */ | ||
| - protected String toString( Tree<ParserRuleContext> tree, int depth ) { | ||
| + protected String toString( Tree<Context> tree, int depth ) { | ||
| StringBuilder sb = new StringBuilder( 2048 ); | ||
| String indent = "", newline = ""; | ||
| sb.append( indent ).append( start( tree ) ); | ||
| - for( Tree<ParserRuleContext> branch : tree.getBranches() ) { | ||
| - ParserRuleContext context = branch.getPayload(); | ||
| + for( Tree<Context> branch : tree.getBranches() ) { | ||
| + Context context = branch.getPayload(); | ||
| - // Recurse for all the branches at this level of the tree. | ||
| if( context instanceof AttributeMapContext ) { | ||
| AttributeMapContext ctx = (AttributeMapContext)context; | ||
| - Tree<ParserRuleContext> parent = branch.getParent(); | ||
| + Tree<Context> parent = branch.getParent(); | ||
| ctx.hasPrecedingPayload( hasPrecedingPayload( parent, ctx ) ); | ||
| ctx.hasFollowingPayload( hasFollowingPayload( parent, ctx ) ); | ||
| + } | ||
| + else if( context instanceof ColumnMapContext ) { | ||
| + // nothing. | ||
| } | ||
| + // Recurse for all the branches at this level of the tree. | ||
| sb.append( newline ).append( toString( branch, depth + getIndentBy() ) ); | ||
| } | ||
| * the given payload. | ||
| */ | ||
| - private List<ParserRuleContext> getConsecutiveRules( | ||
| - Tree<ParserRuleContext> tree, ParserRuleContext p ) { | ||
| - List<ParserRuleContext> result = new ArrayList<ParserRuleContext>(); | ||
| + private List<Context> getConsecutiveRules( | ||
| + Tree<Context> tree, Context p ) { | ||
| + List<Context> result = new ArrayList<Context>(); | ||
| - for( Tree<ParserRuleContext> branch : tree.getBranches() ) { | ||
| + for( Tree<Context> branch : tree.getBranches() ) { | ||
| if( branch.isPayloadClass( p.getClass() ) ) { | ||
| result.add( branch.getPayload() ); | ||
| */ | ||
| public boolean hasPrecedingPayload( | ||
| - Tree<ParserRuleContext> tree, ParserRuleContext payload ) { | ||
| + Tree<Context> tree, Context payload ) { | ||
| return getConsecutiveRules( tree, payload ).indexOf( payload ) > 0; | ||
| } | ||
| */ | ||
| public boolean hasFollowingPayload( | ||
| - Tree<ParserRuleContext> tree, ParserRuleContext payload ) { | ||
| - List<ParserRuleContext> siblings = getConsecutiveRules( tree, payload ); | ||
| + Tree<Context> tree, Context payload ) { | ||
| + List<Context> siblings = getConsecutiveRules( tree, payload ); | ||
| int index = siblings.indexOf( payload ); | ||
| * @return A non-null string, possibly empty. | ||
| */ | ||
| - protected String start( Tree<ParserRuleContext> tree ) { | ||
| + protected String start( Tree<Context> tree ) { | ||
| return start( tree.getPayload() ); | ||
| } | ||
| /** | ||
| * Helper method for returning the start string. | ||
| * | ||
| * @param payload The payload that contains a token to transform into | ||
| * a string. | ||
| - * @return The start string for the parsed item; possibly empty, never null. | ||
| - */ | ||
| - protected String start( ParserRuleContext payload ) { | ||
| - return start( payload.getStart() ); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Helper method for returning the start string. | ||
| - * | ||
| - * @param token The token to transform into a string. | ||
| * @return The start string for the parsed item; possibly empty, never null. | ||
| */ | ||
| - protected String start( Token token ) { | ||
| - return token.toString(); | ||
| + protected String start( Context payload ) { | ||
| + return payload.getStart(); | ||
| } | ||
| /** | ||
| * Returns the transformed syntax for ending the payload item. | ||
| * | ||
| * @param tree The tree that has a payload that contains a token to | ||
| * transform into a string. | ||
| * @return A non-null string, possibly empty. | ||
| */ | ||
| - protected String stop( Tree<ParserRuleContext> tree ) { | ||
| + protected String stop( Tree<Context> tree ) { | ||
| return stop( tree.getPayload() ); | ||
| } | ||
| /** | ||
| * Helper method for returning the stop string. | ||
| * | ||
| * @param payload The payload that contains a token to transform into | ||
| * a string. | ||
| * @return The stop string for the parsed item; possibly empty, never null. | ||
| - */ | ||
| - protected String stop( ParserRuleContext payload ) { | ||
| - return stop( payload.getStop() ); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Helper method for returning the start string. | ||
| - * | ||
| - * @param token The token to transform into a string. | ||
| - * @return The start string for the parsed item; possibly empty, never null. | ||
| */ | ||
| - protected String stop( Token token ) { | ||
| - return token.toString(); | ||
| + protected String stop( Context payload ) { | ||
| + return payload.getStop(); | ||
| } | ||
| * @return ",XMLELEMENT(" ... | ||
| */ | ||
| - @Override | ||
| - public Token getStart() { | ||
| + public String getStart() { | ||
| ParserRuleContext p = getParserRuleContext(); | ||
| QueryParser.TableMapContext ctx = (QueryParser.TableMapContext)p; | ||
| String tableName = ctx.table(1).getText(); | ||
| - return new Token( String.format( ",%s", startElement( tableName ) ) ); | ||
| + return String.format( ",%s", startElement( tableName ) ); | ||
| } | ||
| } |
| -package com.whitemagicsoftware.rxm.xml; | ||
| - | ||
| -import org.antlr.v4.runtime.CommonToken; | ||
| -import static org.antlr.v4.runtime.Token.MIN_USER_TOKEN_TYPE; | ||
| - | ||
| -/** | ||
| - * Avoids having to duplicate common token functionality across the different | ||
| - * parser rule contexts. | ||
| - */ | ||
| -public class Token extends CommonToken { | ||
| - public Token( String text ) { | ||
| - super( MIN_USER_TOKEN_TYPE, text ); | ||
| - } | ||
| - | ||
| - public String toString() { | ||
| - return getText(); | ||
| - } | ||
| -} | ||
| - | ||
| .middle_name > name/first/middle, | ||
| .last_name > name/last, | ||
| +.maiden_name > name/last/original/maiden, | ||
| account > account, | ||
| account.person_id +> person.id, |
| Delta | 76 lines added, 128 lines removed, 52-line decrease |
|---|