context: using System;
  using Antlr.Runtime;
  
  using NHibernate.Engine;
  using NHibernate.Hql.Ast.ANTLR.Util;
  using NHibernate.Persister.Collection;
  using NHibernate.Persister.Entity;
  using NHibernate.SqlCommand;
  using NHibernate.Type;
  using NHibernate.Util;
  
  namespace NHibernate.Hql.Ast.ANTLR.Tree
  {
  	/// <summary>
  	/// Represents a reference to a property or alias expression.  This should duplicate the relevant behaviors in
  	/// PathExpressionParser.
  	/// Author: Joshua Davis
  	/// Ported by: Steve Strong
  	/// </summary>
  	[CLSCompliant(false)]
  	public class DotNode : FromReferenceNode 
  	{
  		private static readonly INHibernateLogger Log = NHibernateLogger.For(typeof(DotNode));
  
  		private const int DerefUnknown = 0;
  		private const int DerefEntity = 1;
  		private const int DerefComponent = 2;
  		private const int DerefCollection = 3;
  		private const int DerefPrimitive = 4;
  		private const int DerefIdentifier = 5;
  		private const int DerefJavaConstant = 6;
  
  		public static bool UseThetaStyleImplicitJoins;
  		public static bool REGRESSION_STYLE_JOIN_SUPPRESSION;
  
  		/// <summary>
  		/// The full path, to the root alias of this dot node.
  		/// </summary>
  		private string _path;
  
  		/// <summary>
  		/// The type of dereference that happened (DEREF_xxx).
  		/// </summary>
  #pragma warning disable 414
  		private int _dereferenceType = DerefUnknown;
  #pragma warning restore 414
  
  		/// <summary>
  		/// The identifier that is the name of the property.
  		/// </summary>
  		private string _propertyName;
  
  		/// <summary>
  		/// The unresolved property path relative to this dot node.
  		/// </summary>
  		private string _propertyPath;
  
  		/// <summary>
  		/// The column names that this resolves to.
  		/// </summary>
  		private string[] _columns;
  
  		/// <summary>
  		/// Fetch join or not.
  		/// </summary>
  		private bool _fetch;
  
  		private FromElement _impliedJoin;
  
  		/// <summary>
  		/// The type of join to create.   Default is an inner join.
  		/// </summary>
  		private JoinType _joinType = JoinType.InnerJoin;
  
  		public DotNode(IToken token) : base(token)
  		{
  		}
  
  		/// <summary>
  		/// Sets the join type for this '.' node structure.
  		/// </summary>
  		public JoinType JoinType
  		{
  			set { _joinType = value; }
  		}
  
  		public bool Fetch
  		{
  			set { _fetch = value;  }
  		}
  
  		public override FromElement GetImpliedJoin()
  		{
  			return _impliedJoin;
  		}
  
  		/// <summary>
  		/// Returns the full path of the node.
  		/// </summary>
  		public override string Path
  		{
  			get
  			{
  				if (_path == null)
  				{
  					var lhs = GetLhs();
  					if (lhs == null)
  					{
  						_path = Text;
  					}
  					else
  					{
  						var rhs = (SqlNode) lhs.NextSibling;
  						_path = lhs.Path + "." + rhs.OriginalText;
  					}
  				}
  				return _path;
  			}
  		}
  
  
  		public string PropertyPath
  		{
  			get { return _propertyPath; }
  			set { _propertyPath = value; }
  		}
  
  		public override void SetScalarColumnText(int i)
  		{
  			string[] sqlColumns = GetColumns();
  			ColumnHelper.GenerateScalarColumns(Walker.ASTFactory, this, sqlColumns, i);
  		}
  
  		public override void ResolveIndex(IASTNode parent) 
  		{
  			if (IsResolved) 
  			{
  				return;
  			}
  
  			IType propertyType = PrepareLhs();			// Prepare the left hand side and get the data type.
  
  			DereferenceCollection( ( CollectionType ) propertyType, true, true, null);
  		}
  
  		public override void ResolveFirstChild()
  		{
  			var lhs = (FromReferenceNode)GetFirstChild();
  			var property = (SqlNode) GetChild(1);
  
  			// Set the attributes of the property reference expression.
  			string propName = property.Text;
  			_propertyName = propName;
  
  			// If the uresolved property path isn't set yet, just use the property name.
  			if (_propertyPath == null)
  			{
  				_propertyPath = propName;
  			}
  
  			// Resolve the LHS fully, generate implicit joins.  Pass in the property name so that the resolver can
  			// discover foreign key (id) properties.
  			lhs.Resolve(true, true, null, this);
  
  			FromElement = lhs.FromElement;			// The 'from element' that the property is in.
  
  			CheckSubclassOrSuperclassPropertyReference(lhs, propName);
  		}
  
  		public override void ResolveInFunctionCall(bool generateJoin, bool implicitJoin)
  		{
  			if (IsResolved)
  			{
  				return;
  			}
  
  			IType propertyType = PrepareLhs();			// Prepare the left hand side and get the data type.
  
  			if (propertyType != null && propertyType.IsCollectionType)
  			{
  				ResolveIndex(null);
  			}
  			else
  			{
  				ResolveFirstChild();
  				Resolve(generateJoin, implicitJoin);
  			}
  		}
  
  		public override void Resolve(bool generateJoin, bool implicitJoin, string classAlias, IASTNode parent)
  		{
  			// If this dot has already been resolved, stop now.
  			if ( IsResolved ) 
  			{
  				return;
  			}
  
  			IType propertyType = PrepareLhs(); // Prepare the left hand side and get the data type.
  
  			// If there is no data type for this node, and we're at the end of the path (top most dot node), then
  			// this might be a Java constant.
  			if ( propertyType == null ) 
  			{
  				if ( parent == null ) 
  				{
  					Walker.LiteralProcessor.LookupConstant( this );
  				}
  				// If the propertyType is null and there isn't a parent, just
  				// stop now... there was a problem resolving the node anyway.
  				return;
  			}
  
  			if ( propertyType.IsComponentType ) 
  			{
  				// The property is a component...
  				CheckLhsIsNotCollection();
  				DereferenceComponent( parent );
  				InitText();
  			}
  			else if ( propertyType.IsEntityType ) 
  			{
  				// The property is another class..
  				CheckLhsIsNotCollection();
  				DereferenceEntity( ( EntityType ) propertyType, implicitJoin, classAlias, generateJoin, parent );
  				InitText();
  			}
  			else if (propertyType.IsCollectionType)
  			{
  				// The property is a collection...
  				CheckLhsIsNotCollection();
  				DereferenceCollection((CollectionType)propertyType, implicitJoin, false, classAlias);
  			}
  			else
  			{
  				// Otherwise, this is a primitive type.
  				if (!CollectionProperties.IsAnyCollectionProperty(_propertyName))
  				{
  					CheckLhsIsNotCollection();
  				}
  				_dereferenceType = DerefPrimitive;
  				InitText();
  			}
  
  			IsResolved = true;
  		}
  
  		
  		public FromReferenceNode GetLhs()
  		{
  
gt: 			var lhs = ((FromReferenceNode)GetChild(0));