Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/rxm.git

Fixed issue with last column map.

AuthorDave Jarvis <email>
Date2015-04-05 18:38:05 GMT-0700
Commit7074b9fed1cb97fb09a47ad86d42098449e7a3bf
Parente6efdf1
build.gradle
}
+// Only invoke this from the command line to create a libs directory containing
+// the dependent JAR files.
+task copyToLib(type: Copy) {
+ into "lib"
+ from configurations.runtime
+}
+
repositories {
mavenCentral()
source/java/com/whitemagicsoftware/rxm/DivergentList.java
import java.util.Iterator;
-import static java.lang.System.out;
-
/**
* Provides the ability to determine the index whereat two lists begin
* to differ in content. Both this list and the list to compare against
* must not contain null objects. Remove all nulls from both lists using
* <code>list.removeAll(Collections.singleton(null))</code> (assuming
* mutable lists).
*/
public class DivergentList<E> extends ArrayList<E> {
+ @SuppressWarnings( "compatibility:-7553330276690450566" )
+ private static final long serialVersionUID = 802724795120260337L;
+
/**
* Default (empty) constructor.
}
}
-
source/java/com/whitemagicsoftware/rxm/ProxyParseTreeListener.java
package com.whitemagicsoftware.rxm;
-import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.antlr.v4.runtime.ParserRuleContext;
-
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.antlr.v4.runtime.tree.ErrorNode;
+import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.antlr.v4.runtime.tree.TerminalNode;
}
+ /**
+ * Notifies the listeners and the context of an enter event.
+ *
+ * @param ctx The rule context to receive an enter event.
+ */
@Override
public void enterEveryRule( ParserRuleContext ctx ) {
getListeners().forEach( listener -> {
listener.enterEveryRule( ctx );
ctx.enterRule( listener );
});
}
+ /**
+ * Notifies the listeners and the context of an exit event.
+ *
+ * @param ctx The rule context to receive an exit event.
+ */
@Override
public void exitEveryRule( ParserRuleContext ctx ) {
}
}
-
source/java/com/whitemagicsoftware/rxm/Tree.java
* @return The tree that was added (i.e., the tree parameter).
*/
+ @SuppressWarnings( "unchecked" )
public Tree<T> addLeaf( Tree<T> tree ) {
getBranches().add( tree );
source/java/com/whitemagicsoftware/rxm/xml/AttributeMapContext.java
package com.whitemagicsoftware.rxm.xml;
-import com.whitemagicsoftware.rxm.Tree;
import com.whitemagicsoftware.rxm.grammar.QueryParser;
*/
private String nextAttribute( String table, String column, String node ) {
- String result = "%s.%s%s";
-
- // If the column name and attribute name are the same, then the
- // "AS" clause is superfluous.
- if( column.equals( node ) ) {
- result = String.format( result, table, column, "" );
- }
- else {
- node = String.format( " AS \"%s\"", node );
- result = String.format( result, table, column, node );
- }
+ // If the column name and attribute name are the same, then the "AS"
+ // clause is superfluous.
+ node = column.equals( node ) ? "" : String.format( " AS \"%s\"", node );
- return result;
+ return String.format( "%s.%s%s", table, column, node );
}
source/java/com/whitemagicsoftware/rxm/xml/Buffered.java
+package com.whitemagicsoftware.rxm.xml;
+
+/**
+ * Isolates creation of the buffer used to write the data.
+ */
+public interface Buffered {
+ default StringBuilder createBuffer() {
+ return new StringBuilder( 2048 );
+ }
+}
+
source/java/com/whitemagicsoftware/rxm/xml/Clause.java
* Common behaviour for various clauses.
*/
-public class Clause extends QueryBaseListener {
+public class Clause extends QueryBaseListener implements Buffered {
private static int INDENT = 2;
- private StringBuilder buffer = new StringBuilder( 2048 );
+ private StringBuilder buffer = createBuffer();
/**
source/java/com/whitemagicsoftware/rxm/xml/ColumnMapContext.java
package com.whitemagicsoftware.rxm.xml;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import java.util.stream.Collectors;
-
import com.whitemagicsoftware.rxm.DivergentList;
-import com.whitemagicsoftware.rxm.Tree;
import com.whitemagicsoftware.rxm.grammar.QueryParser;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.Vocabulary;
/**
* Transforms <b><code>column &gt; path</code></b> into an
* <code>XMLELEMENT</code> expression.
*/
public class ColumnMapContext extends Context {
- private final static String T_SLASH =
- QueryParser.VOCABULARY.getLiteralName( QueryParser.T_SLASH );
+ // The most recent column mapping path that does not contain ellipses.
+ private QueryParser.ElementPathContext explicitPath;
/**
DivergentList<String> thisList = listElementNames();
DivergentList<String> prevList = listElementNamesPrev();
-
- if( hasEllipsesPath() ) {
- System.out.printf( "ELLIPSES: %s%n", thisList.toString() );
- System.out.printf( "ELLIPSES PREV: %s%n", prevList.toString() );
- }
-
- if( hasEllipsesPath() && prevList.size() > 0 ) {
- thisList.addAll( 0, prevList.subList( 0, prevList.size() - 1 ) );
- System.out.println( "thisList: " + thisList.toString() );
- }
// If there are no common elements with the previous list, then this is
*/
private DivergentList<String> listElementNamesNext() {
- DivergentList<String> prev = listElementNames( getNextContext() );
-
- if( hasEllipsesPath() ) {
- System.out.printf( "Prev: %s%n", prev.toString() );
- }
-
- return prev;
+ return listElementNames( getNextContext() );
}
*/
protected List<QueryParser.ElementContext> element() {
- return (hasEllipsesPath() ?
+ List<QueryParser.ElementContext> result = (hasEllipsesPath() ?
ellipsesPath().elementPath() :
elementPath()).element();
+
+ if( hasEllipsesPath() ) {
+ result.addAll( 0, explicitPath() );
+ }
+
+ return result;
+ }
+
+ private List<QueryParser.ElementContext> explicitPath() {
+ List<QueryParser.ElementContext> result =
+ new ArrayList<QueryParser.ElementContext>();
+
+ QueryParser.ElementPathContext explicitPath = getExplicitPath();
+
+ if( explicitPath != null ) {
+ result.addAll( explicitPath.element() );
+ result.remove( result.size() - 1 );
+ }
+
+ return result;
+ }
+
+ protected void setExplicitPath( QueryParser.ElementPathContext epc ) {
+ this.explicitPath = epc;
+ }
+
+ private QueryParser.ElementPathContext getExplicitPath() {
+ return this.explicitPath;
}
source/java/com/whitemagicsoftware/rxm/xml/Context.java
* Represents a wrapper class for ParserRuleContext.
*/
-public abstract class Context {
+public abstract class Context implements Buffered {
private ParserRuleContext parserRuleContext;
private Context nextContext;
protected Context getPrevContext() {
return this.prevContext;
- }
-
- protected StringBuilder createBuffer() {
- return new StringBuilder( 2048 );
}
source/java/com/whitemagicsoftware/rxm/xml/JoinClause.java
package com.whitemagicsoftware.rxm.xml;
-import com.whitemagicsoftware.rxm.Tree;
-import com.whitemagicsoftware.rxm.grammar.QueryBaseListener;
import com.whitemagicsoftware.rxm.grammar.QueryParser;
-
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.tree.TerminalNode;
/**
source/java/com/whitemagicsoftware/rxm/xml/SelectClause.java
import com.whitemagicsoftware.rxm.Tree;
-import com.whitemagicsoftware.rxm.grammar.QueryBaseListener;
import com.whitemagicsoftware.rxm.grammar.QueryParser;
import org.antlr.v4.runtime.ParserRuleContext;
public class SelectClause extends Clause {
private Tree<Context> tree;
+
+ // The most recent column mapping path that does not contain ellipses.
+ private QueryParser.ElementPathContext explicitPath;
/**
@Override
public void enterColumnMap( QueryParser.ColumnMapContext ctx ) {
- addLeaf( new ColumnMapContext( ctx, getTableName() ) );
+ ColumnMapContext cmc = new ColumnMapContext( ctx, getTableName() );
+
+ if( cmc.hasEllipsesPath() ) {
+ // A column mapping always has at least one non-ellipses mapping that
+ // precedes it. (See directly below.)
+ cmc.setExplicitPath( getExplicitPath() );
+ }
+ else {
+ // A column mapping without ellipses must be stored for later use by
+ // column mappings with ellipses.
+ setExplicitPath( cmc.elementPath() );
+ }
+
+ addLeaf( cmc );
+ }
+
+ /**
+ * Stores the latest column map's context that has no ellipses.
+ *
+ * @param epc The most recent element path that does not use ellipses.
+ */
+ protected void setExplicitPath( QueryParser.ElementPathContext epc ) {
+ this.explicitPath = epc;
+ }
+
+ private QueryParser.ElementPathContext getExplicitPath() {
+ return this.explicitPath;
}
}
}
-
source/java/com/whitemagicsoftware/rxm/xml/SelectTree.java
package com.whitemagicsoftware.rxm.xml;
+import com.whitemagicsoftware.rxm.PeekingIterator;
+import com.whitemagicsoftware.rxm.Tree;
+
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-
-import com.whitemagicsoftware.rxm.PeekingIterator;
-import com.whitemagicsoftware.rxm.Tree;
-
-import org.antlr.v4.runtime.Token;
/**
* Helps generate a SQL/XML SELECT clause.
*/
-public class SelectTree extends Tree<Context> {
+public class SelectTree extends Tree<Context> implements Buffered {
public static final int INDENT = 2;
*/
protected String toString( Tree<Context> tree, int depth ) {
- StringBuilder sb = new StringBuilder( 2048 );
+ StringBuilder sb = createBuffer();
String indent = "", newline = "";
if( beautify() ) {
indent = getIndent( depth );
newline = getNewline();
}
sb.append( indent ).append( start( tree ) );
- // Immediately previous column map (if any).
- ColumnMapContext priorColumnMap = null;
List<Tree<Context>> branches = tree.getBranches();
PeekingIterator<Tree<Context>> i = createIterator( branches.iterator() );
else if( context instanceof ColumnMapContext ) {
if( i.hasNext() ) {
- Tree<Context> next = i.peek();
-
- context.setNextContext( next.getPayload() );
- context.setPrevContext( prevContext );
+ context.setNextContext( i.peek().getPayload() );
}
+
+ // Ensure that all the column maps get the previous context. This
+ // helps when using the divergent list to calculate how many nested
+ // elements are in common.
+ context.setPrevContext( prevContext );
}
* that is before the given payload.
*/
- public boolean hasPrecedingPayload(
- Tree<Context> tree, Context payload ) {
+ public boolean hasPrecedingPayload( Tree<Context> tree, Context payload ) {
return getConsecutiveRules( tree, payload ).indexOf( payload ) > 0;
}
* that is after the given payload.
*/
- public boolean hasFollowingPayload(
- Tree<Context> tree, Context payload ) {
+ public boolean hasFollowingPayload( Tree<Context> tree, Context payload ) {
List<Context> siblings = getConsecutiveRules( tree, payload );
int index = siblings.indexOf( payload );
}
}
-
source/java/com/whitemagicsoftware/rxm/xml/TableMapContext.java
}
-
source/java/com/whitemagicsoftware/rxm/xml/WhereClause.java
package com.whitemagicsoftware.rxm.xml;
-import com.whitemagicsoftware.rxm.grammar.QueryBaseListener;
import com.whitemagicsoftware.rxm.grammar.QueryParser;
}
}
-
test/elements.rxm
+root > people,
+person > person,
+.first_name > name/first,
+.last_name > .../last,
+
Delta125 lines added, 87 lines removed, 38-line increase