criteriaquerytranslator.cs

来自「NHibernate NET开发者所需的」· CS 代码 · 共 702 行 · 第 1/2 页

CS
702
字号
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Iesi.Collections.Generic;
using NHibernate.Engine;
using NHibernate.Criterion;
using NHibernate.Hql.Util;
using NHibernate.Impl;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
using NHibernate.Type;
using NHibernate.Util;

namespace NHibernate.Loader.Criteria
{
	public class CriteriaQueryTranslator : ICriteriaQuery
	{
		public static readonly string RootSqlAlias = CriteriaUtil.RootAlias + '_';

		private readonly ICriteriaQuery outerQueryTranslator;

		private readonly CriteriaImpl rootCriteria;
		private readonly string rootEntityName;
		private readonly string rootSQLAlias;
		private readonly int aliasCount = 0;

		private readonly IDictionary<ICriteria, string> criteriaEntityNames = new LinkedHashMap<ICriteria, string>();
		private readonly ISet<ICollectionPersister> criteriaCollectionPersisters = new HashedSet<ICollectionPersister>();

		private readonly IDictionary<ICriteria, string> criteriaSQLAliasMap = new Dictionary<ICriteria, string>();
		private readonly IDictionary<string, ICriteria> aliasCriteriaMap = new Dictionary<string, ICriteria>();
		private readonly IDictionary<string, ICriteria> associationPathCriteriaMap = new LinkedHashMap<string, ICriteria>();
		private readonly IDictionary<string, JoinType> associationPathJoinTypesMap = new LinkedHashMap<string, JoinType>();

		private readonly ISessionFactoryImplementor sessionFactory;
		private int indexForAlias = 0;

		public CriteriaQueryTranslator(
			ISessionFactoryImplementor factory,
			CriteriaImpl criteria,
			string rootEntityName,
			string rootSQLAlias,
			ICriteriaQuery outerQuery)
			: this(factory, criteria, rootEntityName, rootSQLAlias)
		{
			outerQueryTranslator = outerQuery;
		}

		public CriteriaQueryTranslator(
			ISessionFactoryImplementor factory,
			CriteriaImpl criteria,
			string rootEntityName,
			string rootSQLAlias)
		{
			rootCriteria = criteria;
			this.rootEntityName = rootEntityName;
			sessionFactory = factory;
			this.rootSQLAlias = rootSQLAlias;

			CreateAliasCriteriaMap();
			CreateAssociationPathCriteriaMap();
			CreateCriteriaEntityNameMap();
			CreateCriteriaCollectionPersisters();
			CreateCriteriaSQLAliasMap();
		}

		public string GenerateSQLAlias()
		{
			return StringHelper.GenerateAlias(rootSQLAlias, aliasCount);
		}


		public int GetIndexForAlias()
		{
			return indexForAlias++;
		}

		private ICriteria GetAliasedCriteria(string alias)
		{
			ICriteria result;
			aliasCriteriaMap.TryGetValue(alias, out result);
			return result;
		}

		public bool IsJoin(string path)
		{
			return associationPathCriteriaMap.ContainsKey(path);
		}

		public JoinType GetJoinType(string path)
		{
			JoinType result;
			if (associationPathJoinTypesMap.TryGetValue(path, out result))
				return result;
			else
				return JoinType.InnerJoin;
		}

		public ICriteria GetCriteria(string path)
		{
			ICriteria result;
			associationPathCriteriaMap.TryGetValue(path, out result);
			return result;
		}

		public ISet<string> GetQuerySpaces()
		{
			ISet<string> result = new HashedSet<string>();

			foreach (string entityName in criteriaEntityNames.Values)
			{
				result.AddAll(Factory.GetEntityPersister(entityName).QuerySpaces);
			}

			foreach (ICollectionPersister collectionPersister in criteriaCollectionPersisters)
			{
				result.AddAll(collectionPersister.CollectionSpaces);
			}
			return result;
		}

		private void CreateAliasCriteriaMap()
		{
			aliasCriteriaMap[rootCriteria.Alias] = rootCriteria;

			foreach (ICriteria subcriteria in rootCriteria.IterateSubcriteria())
			{
				if (subcriteria.Alias != null)
				{
					try
					{
						aliasCriteriaMap.Add(subcriteria.Alias, subcriteria);
					}
					catch (ArgumentException ae)
					{
						throw new QueryException("duplicate alias: " + subcriteria.Alias, ae);
					}
				}
			}
		}

		private void CreateAssociationPathCriteriaMap()
		{
			foreach (CriteriaImpl.Subcriteria crit in rootCriteria.IterateSubcriteria())
			{
				string wholeAssociationPath = GetWholeAssociationPath(crit);
				try
				{
					associationPathCriteriaMap.Add(wholeAssociationPath, crit);
				}
				catch (ArgumentException ae)
				{
					throw new QueryException("duplicate association path: " + wholeAssociationPath, ae);
				}

				try
				{
					associationPathJoinTypesMap.Add(wholeAssociationPath, crit.JoinType);
				}
				catch (ArgumentException ae)
				{
					throw new QueryException("duplicate association path: " + wholeAssociationPath, ae);
				}
			}
		}

		private string GetWholeAssociationPath(CriteriaImpl.Subcriteria subcriteria)
		{
			string path = subcriteria.Path;

			// some messy, complex stuff here, since createCriteria() can take an
			// aliased path, or a path rooted at the creating criteria instance
			ICriteria parent = null;
			if (path.IndexOf('.') > 0)
			{
				// if it is a compound path
				string testAlias = StringHelper.Root(path);
				if (!testAlias.Equals(subcriteria.Alias))
				{
					// and the qualifier is not the alias of this criteria
					//      -> check to see if we belong to some criteria other
					//          than the one that created us
					aliasCriteriaMap.TryGetValue(testAlias, out parent);
				}
			}
			if (parent == null)
			{
				// otherwise assume the parent is the the criteria that created us
				parent = subcriteria.Parent;
			}
			else
			{
				path = StringHelper.Unroot(path);
			}

			if (parent.Equals(rootCriteria))
			{
				// if its the root criteria, we are done
				return path;
			}
			else
			{
				// otherwise, recurse
				return GetWholeAssociationPath((CriteriaImpl.Subcriteria)parent) + '.' + path;
			}
		}

		private void CreateCriteriaEntityNameMap()
		{
			criteriaEntityNames[rootCriteria] = rootEntityName;

			foreach (KeyValuePair<string, ICriteria> me in associationPathCriteriaMap)
			{
				criteriaEntityNames[me.Value] = GetPathEntityName(me.Key);
			}
		}

		private void CreateCriteriaCollectionPersisters()
		{
			foreach (KeyValuePair<string, ICriteria> me in associationPathCriteriaMap)
			{
				IJoinable joinable = GetPathJoinable(me.Key);
				if (joinable.IsCollection)
				{
					criteriaCollectionPersisters.Add((ICollectionPersister)joinable);
				}
			}
		}

		private IJoinable GetPathJoinable(string path)
		{
			IJoinable last = (IJoinable)Factory.GetEntityPersister(rootEntityName);
			IPropertyMapping lastEntity = (IPropertyMapping)last;

			string componentPath = "";

			StringTokenizer tokens = new StringTokenizer(path, ".", false);
			foreach (string token in tokens)
			{
				componentPath += token;
				IType type = lastEntity.ToType(componentPath);
				if (type.IsAssociationType)
				{
					IAssociationType atype = (IAssociationType)type;
					last = atype.GetAssociatedJoinable(Factory);
					lastEntity = (IPropertyMapping)Factory.GetEntityPersister(atype.GetAssociatedEntityName(Factory));
					componentPath = "";
				}
				else if (type.IsComponentType)
				{
					componentPath += '.';
				}
				else
				{
					throw new QueryException("not an association: " + componentPath);
				}
			}
			return last;
		}

		private string GetPathEntityName(string path)
		{
			IQueryable persister = (IQueryable)sessionFactory.GetEntityPersister(rootEntityName);
			StringTokenizer tokens = new StringTokenizer(path, ".", false);
			string componentPath = "";
			foreach (string token in tokens)
			{
				componentPath += token;
				IType type = persister.ToType(componentPath);
				if (type.IsAssociationType)
				{
					IAssociationType atype = (IAssociationType)type;
					persister = (IQueryable)sessionFactory.GetEntityPersister(atype.GetAssociatedEntityName(sessionFactory));
					componentPath = "";
				}
				else if (type.IsComponentType)
				{
					componentPath += '.';
				}
				else
				{
					throw new QueryException("not an association: " + componentPath);
				}
			}
			return persister.EntityName;
		}

		public int SQLAliasCount
		{
			get { return criteriaSQLAliasMap.Count; }
		}

		private void CreateCriteriaSQLAliasMap()
		{
			int i = 0;

			foreach (KeyValuePair<ICriteria, string> me in criteriaEntityNames)
			{
				ICriteria crit = me.Key;
				string alias = crit.Alias;
				if (alias == null)
				{
					alias = me.Value;
				}
				criteriaSQLAliasMap[crit] = StringHelper.GenerateAlias(alias, i++);
			}
			criteriaSQLAliasMap[rootCriteria] = rootSQLAlias;
		}

		public CriteriaImpl RootCriteria
		{
			get { return rootCriteria; }
		}

		public QueryParameters GetQueryParameters()
		{
			ArrayList values = new ArrayList();
			ArrayList types = new ArrayList();

			foreach (CriteriaImpl.CriterionEntry ce in rootCriteria.IterateExpressionEntries())
			{
				TypedValue[] tv = ce.Criterion.GetTypedValues(ce.Criteria, this);
				for (int i = 0; i < tv.Length; i++)
				{
					values.Add(tv[i].Value);
					types.Add(tv[i].Type);
				}
			}
			if (rootCriteria.Projection != null)
			{
				TypedValue[] tv = rootCriteria.Projection.GetTypedValues(rootCriteria.ProjectionCriteria, this);
				for (int i = 0; i < tv.Length; i++)
				{
					values.Add(tv[i].Value);
					types.Add(tv[i].Type);
				}
			}

			object[] valueArray = values.ToArray();
			IType[] typeArray = (IType[])types.ToArray(typeof(IType));

			RowSelection selection = new RowSelection();
			selection.FirstRow = rootCriteria.FirstResult;
			selection.MaxRows = rootCriteria.MaxResults;
			selection.Timeout = rootCriteria.Timeout;
			selection.FetchSize = rootCriteria.FetchSize;

			IDictionary lockModes = new Hashtable();
			foreach (DictionaryEntry me in rootCriteria.LockModes)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?