Author: pgmjsd
Date: 2006-04-12 09:12:03 -0400 (Wed, 12 Apr 2006)
New Revision: 9742
Added:
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/HqlResolver.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/HqlResolverASTFactory.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/RangeNode.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContext.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContextImpl.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/StatementNode.java
Removed:
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolverASTFactory.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/StatementNode.java
Modified:
branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g
branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java
Log:
Moved the resolver stuff into it's own package. The unit test now resolves 'FROM Animal'.
Modified: branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g 2006-04-12 13:12:03 UTC (rev 9742)
@@ -40,34 +40,13 @@
{
private static Log log = LogFactory.getLog( HqlBaseResolver.class );
- private int level = 0;
- private List inputContext = new ArrayList();
- private List outputContext = new ArrayList();
+ // Semantic action methods, overridden in subclasses for clarity.
- protected void pushContext(AST outputAst,AST inputAst) {
- level++;
- inputContext.add(inputAst);
- outputContext.add(outputAst);
- if (log.isDebugEnabled()) {
- log.debug("Pushed context: level = " + level + " input is " + inputAst.toStringTree());
- }
- }
+ protected void pushContext(AST outputAst,AST inputAst) { }
- protected void popContext() {
- level--;
- AST n = (AST)inputContext.remove(inputContext.size() - 1);
- outputContext.remove(outputContext.size() - 1);
- if (log.isDebugEnabled()) {
- log.debug("Popped context: level = " + level + " input was " + n.toStringTree());
- }
- }
+ protected void popContext() { }
- protected AST getCurrentContext(boolean input) {
- return (AST)((input) ? inputContext.get(inputContext.size() - 1)
- : outputContext.get(outputContext.size() - 1));
- }
-
- protected int getLevel() { return level; }
+ protected void defineRange(AST range,String path,AST alias, AST fetch) { }
}
// The main statement rule.
@@ -120,8 +99,15 @@
: #(f:FROM { pushContext(#fromClause,f); } ( range | join | filter ) * )
;
+// Antlr note: The '!' prevents the automatic creation of the output AST, so the semantic action can do it.
range
- : #(RANGE path (ALIAS)? (FETCH)? )
+ {
+ String p = "";
+ }
+ : #(RANGE p=pathAsString! (a:ALIAS!)? (f:FETCH!)? )
+ {
+ defineRange(#range,p,a,f); // Set up the output tree.
+ }
;
join
@@ -178,6 +164,20 @@
| #(DOT path identifier)
;
+// Matches a path and returns the normalized string for the path (usually
+// fully qualified a class name).
+pathAsString returns [String p] {
+ p = "???";
+ String x = "?x?";
+ }
+ : a:identifier { p = a.getText(); }
+ | #(DOT x=pathAsString y:identifier) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(x).append(".").append(y.getText());
+ p = buf.toString();
+ }
+ ;
+
identifier
: (IDENT | WEIRD_IDENT)
;
Deleted: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -1,16 +0,0 @@
-package org.hibernate.hql.ast;
-
-import org.hibernate.hql.antlr.HqlBaseResolver;
-
-/**
- * Implements the methods for the HqlBaseResolver.
- * <br>User: Joshua Davis
- * Date: Apr 1, 2006
- * Time: 7:40:42 AM
- */
-public class HqlResolver extends HqlBaseResolver {
- public HqlResolver() {
- super();
- setASTFactory(new HqlResolverASTFactory()); // Create nodes that track line and column number.
- }
-}
Deleted: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolverASTFactory.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolverASTFactory.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolverASTFactory.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -1,24 +0,0 @@
-package org.hibernate.hql.ast;
-
-import org.hibernate.hql.antlr.HqlRTokenTypes;
-import org.hibernate.hql.ast.tree.StatementNode;
-
-/**
- * AST factory for the resolver phase.
- * <br>User: Joshua Davis
- * Date: Apr 3, 2006
- * Time: 7:58:16 AM
- */
-public class HqlResolverASTFactory extends HqlASTFactory implements HqlRTokenTypes {
- public Class getASTNodeType(int tokenType) {
- // Statement nodes:
- switch (tokenType) {
- case QUERY :
- case UPDATE:
- case DELETE:
- case INSERT:
- return StatementNode.class;
- }
- return super.getASTNodeType(tokenType);
- }
-}
Copied: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/HqlResolver.java (from rev 9741, branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java)
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/HqlResolver.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -0,0 +1,68 @@
+package org.hibernate.hql.ast.resolve;
+
+import org.hibernate.hql.antlr.HqlBaseResolver;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import java.util.List;
+import java.util.ArrayList;
+
+import antlr.collections.AST;
+
+/**
+ * Implements the methods for the HqlBaseResolver.
+ * <br>User: Joshua Davis
+ * Date: Apr 1, 2006
+ * Time: 7:40:42 AM
+ */
+public class HqlResolver extends HqlBaseResolver {
+ private static Log log = LogFactory.getLog( HqlResolver.class );
+
+ private int level = 0;
+ private List inputContext = new ArrayList();
+ private List outputContext = new ArrayList();
+ private ResolverContext context; // Provides acces to the session factory via an interface.
+
+ public HqlResolver() {
+ super();
+ setASTFactory(new HqlResolverASTFactory()); // Create nodes that track line and column number.
+ }
+
+
+ protected void pushContext(AST outputAst,AST inputAst) {
+ level++;
+ inputContext.add(inputAst);
+ outputContext.add(outputAst);
+ if (log.isDebugEnabled()) {
+ log.debug("Pushed context: level = " + level + " input is " + inputAst.toStringTree());
+ }
+ }
+
+ protected void popContext() {
+ level--;
+ AST n = (AST)inputContext.remove(inputContext.size() - 1);
+ outputContext.remove(outputContext.size() - 1);
+ if (log.isDebugEnabled()) {
+ log.debug("Popped context: level = " + level + " input was " + n.toStringTree());
+ }
+ }
+
+ protected AST getCurrentContext(boolean input) {
+ return (AST)((input) ? inputContext.get(inputContext.size() - 1)
+ : outputContext.get(outputContext.size() - 1));
+ }
+
+ protected int getLevel() { return level; }
+
+ protected void defineRange(AST range, String path, AST alias, AST fetch) {
+ RangeNode r = (RangeNode) range;
+ r.setPath(path);
+ r.setPersister(context.lookupPersister(path));
+ r.setFetch(fetch != null);
+ r.setAlias(alias != null ? alias.getText() : null);
+ }
+
+ public void initialize(ResolverContext resolverContext) {
+ context = resolverContext;
+ }
+}
Copied: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/HqlResolverASTFactory.java (from rev 9741, branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolverASTFactory.java)
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolverASTFactory.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/HqlResolverASTFactory.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -0,0 +1,26 @@
+package org.hibernate.hql.ast.resolve;
+
+import org.hibernate.hql.antlr.HqlRTokenTypes;
+import org.hibernate.hql.ast.HqlASTFactory;
+
+/**
+ * AST factory for the resolver phase.
+ * <br>User: Joshua Davis
+ * Date: Apr 3, 2006
+ * Time: 7:58:16 AM
+ */
+public class HqlResolverASTFactory extends HqlASTFactory implements HqlRTokenTypes {
+ public Class getASTNodeType(int tokenType) {
+ // Statement nodes:
+ switch (tokenType) {
+ case QUERY :
+ case UPDATE:
+ case DELETE:
+ case INSERT:
+ return StatementNode.class;
+ case RANGE:
+ return RangeNode.class;
+ }
+ return super.getASTNodeType(tokenType);
+ }
+}
Added: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/RangeNode.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/RangeNode.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/RangeNode.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -0,0 +1,64 @@
+package org.hibernate.hql.ast.resolve;
+
+import org.hibernate.hql.ast.tree.Node;
+import org.hibernate.hql.ast.tree.DisplayableNode;
+import org.hibernate.persister.entity.EntityPersister;
+
+/**
+ * Represents an element of a FROM clause, e.g. "from Animal a"
+ * <br>User: Joshua Davis
+ * Date: Apr 12, 2006
+ * Time: 7:31:17 AM
+ */
+public class RangeNode extends Node implements DisplayableNode {
+ private String path;
+ private String alias;
+ private EntityPersister persister;
+ private boolean fetch = false;
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public EntityPersister getPersister() {
+ return persister;
+ }
+
+ public void setPersister(EntityPersister persister) {
+ this.persister = persister;
+ }
+
+ public boolean isFetch() {
+ return fetch;
+ }
+
+ public void setFetch(boolean fetch) {
+ this.fetch = fetch;
+ }
+
+ public String getAlias() {
+ return alias;
+ }
+
+ public void setAlias(String alias) {
+ this.alias = alias;
+ }
+
+
+ public String toString() {
+ return "RangeNode{" +
+ "path='" + path + '\'' +
+ ", alias='" + alias + '\'' +
+ ", persister=" + persister +
+ ", fetch=" + fetch +
+ '}';
+ }
+
+ public String getDisplayText() {
+ return toString();
+ }
+}
Added: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContext.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContext.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContext.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -0,0 +1,13 @@
+package org.hibernate.hql.ast.resolve;
+
+import org.hibernate.persister.entity.EntityPersister;
+
+/**
+ * Looks up persisters and other things by name.
+ * <br>User: Joshua Davis
+ * Date: Apr 12, 2006
+ * Time: 7:34:11 AM
+ */
+public interface ResolverContext {
+ EntityPersister lookupPersister(String path);
+}
Added: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContextImpl.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContextImpl.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/ResolverContextImpl.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -0,0 +1,36 @@
+package org.hibernate.hql.ast.resolve;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.MappingException;
+import org.hibernate.persister.entity.EntityPersister;
+
+/**
+ * Implements the resolver's context with a session factory.
+ * <br>User: Joshua Davis
+ * Date: Apr 12, 2006
+ * Time: 7:35:31 AM
+ */
+public class ResolverContextImpl implements ResolverContext {
+ private SessionFactoryImplementor sfi;
+
+ public ResolverContextImpl(SessionFactoryImplementor sfi) {
+ this.sfi = sfi;
+ }
+
+ public EntityPersister lookupPersister(String name) {
+ // First, try to get the persister using the class name directly.
+ try {
+ return sfi.getEntityPersister( name );
+ }
+ catch ( MappingException ignore ) {
+ // unable to locate it using this name
+ }
+
+ // If that didn't work, try using the 'import' name.
+ String importedClassName = sfi.getImportedClassName( name );
+ if ( importedClassName == null ) {
+ return null;
+ }
+ return sfi.getEntityPersister( importedClassName );
+ }
+}
Copied: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/StatementNode.java (from rev 9741, branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/StatementNode.java)
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/StatementNode.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/resolve/StatementNode.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -0,0 +1,12 @@
+package org.hibernate.hql.ast.resolve;
+
+import org.hibernate.hql.ast.tree.Node;
+
+/**
+ * Represents a statement (SELECT, UPDATE, INSERT, DELETE) in the resolved HQL tree.
+ * <br>User: Joshua Davis
+ * Date: Apr 3, 2006
+ * Time: 8:00:55 AM
+ */
+public class StatementNode extends Node {
+}
Deleted: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/StatementNode.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/StatementNode.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/StatementNode.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -1,10 +0,0 @@
-package org.hibernate.hql.ast.tree;
-
-/**
- * Represents a statement (SELECT, UPDATE, INSERT, DELETE) in the resolved HQL tree.
- * <br>User: Joshua Davis
- * Date: Apr 3, 2006
- * Time: 8:00:55 AM
- */
-public class StatementNode extends Node {
-}
Modified: branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java 2006-04-11 11:57:40 UTC (rev 9741)
+++ branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java 2006-04-12 13:12:03 UTC (rev 9742)
@@ -4,12 +4,14 @@
import antlr.TokenStreamException;
import antlr.collections.AST;
import junit.framework.Test;
-import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.hibernate.hql.antlr.HqlRTokenTypes;
-import org.hibernate.hql.ast.HqlResolver;
-import org.hibernate.hql.ast.tree.StatementNode;
+import org.hibernate.hql.ast.resolve.HqlResolver;
+import org.hibernate.hql.ast.resolve.StatementNode;
+import org.hibernate.hql.ast.resolve.ResolverContextImpl;
import org.hibernate.hql.ast.util.ASTPrinter;
+import org.hibernate.test.TestCase;
+import org.hibernate.engine.SessionFactoryImplementor;
/**
* Tests the new HQL resolver phase.
@@ -24,7 +26,6 @@
super(n);
}
-
public void testSimpleHql() throws Exception {
// First, get an AST by parsing some HQL text.
AST ast = resolve("from Animal");
@@ -38,13 +39,67 @@
// Now, pass it though the resolver phase, which yeilds
// a processed HQL AST.
HqlResolver resolver = new HqlResolver();
+ ResolverContextImpl context = new ResolverContextImpl(getSessionFactoryImplementor());
+ resolver.initialize(context); // Give the resolver a fake context.
resolver.statement(hqlAst);
AST resolvedHql = resolver.getAST();
- System.out.println(hqlrPrinter.showAsString(resolvedHql,"Resolved AST : " + resolvedHql.toStringTree() + "" ));
+ System.out.println(hqlrPrinter.showAsString(resolvedHql,
+ "Resolved AST : " + resolvedHql.toStringTree() + "" ));
return resolvedHql;
}
+ protected SessionFactoryImplementor getSessionFactoryImplementor() {
+ SessionFactoryImplementor factory = ( SessionFactoryImplementor ) getSessions();
+ if ( factory == null ) {
+ throw new NullPointerException( "Unable to create factory!" );
+ }
+ return factory;
+ }
+
public static Test suite() {
return new TestSuite(HqlResolverTest.class);
}
+
+ protected String[] getMappings() {
+ return new String[]{
+ "hql/Animal.hbm.xml",
+ "hql/EntityWithCrazyCompositeKey.hbm.xml",
+ "batchfetch/ProductLine.hbm.xml",
+ "cid/Customer.hbm.xml",
+ "cid/Order.hbm.xml",
+ "cid/LineItem.hbm.xml",
+ "cid/Product.hbm.xml",
+ "legacy/Baz.hbm.xml",
+ "legacy/Category.hbm.xml",
+ "legacy/Commento.hbm.xml",
+ "legacy/Container.hbm.xml",
+ "legacy/Custom.hbm.xml",
+ "legacy/Eye.hbm.xml",
+ "legacy/Fee.hbm.xml",
+ "legacy/FooBar.hbm.xml",
+ "legacy/Fum.hbm.xml",
+ "legacy/Glarch.hbm.xml",
+ "legacy/Holder.hbm.xml",
+ "legacy/Many.hbm.xml",
+ "legacy/Marelo.hbm.xml",
+ "legacy/MasterDetail.hbm.xml",
+ "legacy/Middle.hbm.xml",
+ "legacy/Multi.hbm.xml",
+ "legacy/Nameable.hbm.xml",
+ "legacy/One.hbm.xml",
+ "legacy/Qux.hbm.xml",
+ "legacy/Simple.hbm.xml",
+ "legacy/SingleSeveral.hbm.xml",
+ "legacy/WZ.hbm.xml",
+ "legacy/UpDown.hbm.xml",
+ "compositeelement/Parent.hbm.xml",
+ "onetoone/joined/Person.hbm.xml",
+ "hql/CrazyIdFieldNames.hbm.xml"
+ };
+ }
+
+ protected boolean recreateSchema() {
+ // we do not need to create the schema for these parser tests
+ return false;
+ }
}
|