public static XElement GetFieldRef(ISpModelContext modelContext, Expression node)
		{
			if (node == null)
			{
				throw new ArgumentNullException("node");
			}

			node = node.StripQuotes();

			if (node.NodeType != ExpressionType.MemberAccess)
			{
				throw new NotSupportedException(string.Format("{0} should be a member access", node));
			}

			var memberExpression = (MemberExpression) node;
			var memberName = memberExpression.Member.Name;

			if (memberExpression.Expression.NodeType != ExpressionType.Parameter)
			{
				throw new NotSupportedException(string.Format("{0} not supported", memberExpression));
			}

			return new XElement(Tags.FieldRef,
				new XAttribute(Tags.Name, modelContext.GetSpFieldInternalName(memberExpression.Member.DeclaringType, memberName)));
		}
		public XElement Translate(ISpModelContext modelContext, Expression predicate)
		{
			ModelContext = modelContext;

			Visit(predicate);

			return Root;
		}
		protected override Expression VisitConstant(ConstantExpression node)
		{
			if (typeof (ISpModelContext).IsAssignableFrom(node.Type))
			{
				ModelContext = (ISpModelContext) node.Value;
			}
			
			return node;
		}
		public XElement Translate(ISpModelContext modelContext, Expression node)
		{
			node = TreeVisitors.Aggregate(node, (current, treeVisitor) => treeVisitor.Visit(current));

			var queryElement = new XElement(Tags.Query, 
				Translators.Select(translator => translator.Translate(modelContext, node)));

			return queryElement;
		}
		public static XElement GetValue(ISpModelContext modelContext, MemberExpression memberExpression, Expression node)
		{
			if (node == null)
			{
				throw new ArgumentNullException("node");
			}

			node = node.StripQuotes();

			if (node.NodeType != ExpressionType.Constant)
			{
				throw new NotSupportedException(string.Format("{0} should be a constant expression", node));
			}

			var constantExpression = (ConstantExpression)node;

			return new XElement(Tags.Value, 
				new XAttribute(Tags.Type, modelContext.GetSpFieldTypeAsString(memberExpression.Member.DeclaringType, memberExpression.Member.Name)),
				Convert.ToString(modelContext.ConvertToSpValue(memberExpression.Member.DeclaringType, memberExpression.Member.Name, constantExpression.Value)));
		}