PageRenderTime 155ms CodeModel.GetById 149ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Otis/Parsing/ExpressionParser.cs

http://otis-lib.googlecode.com/
C# | 129 lines | 109 code | 19 blank | 1 comment | 15 complexity | dfe36007571e3a1bfde0df0bec93958e MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Reflection;
  4using System.Text;
  5using System.Text.RegularExpressions;
  6using Otis.CodeGen;
  7
  8namespace Otis.Parsing
  9{
 10	class ExpressionParser
 11	{
 12		static Regex s_regex = new Regex(@"^\w+:.+\w$"); // match all like 'xxx:....'
 13		static Regex s_literal = new Regex(@"^\[.+\]$"); // match all like '[....]'
 14		static Regex s_projection = new Regex(@"^(\s*[^\s:=>,]+\s*=>\s*[^\s:=>,]+\s*;)*(\s*[^\s:=>,]+\s*=>\s*[^\s:=>,]+\s*);?$"); // match all like 'a=>b;c=>d'
 15
 16		public static bool IsAggregateExpression(string expression)
 17		{
 18			return s_regex.IsMatch(expression.Trim());
 19		}
 20
 21		public static bool IsLiteralExpression(string expression)
 22		{
 23			return s_literal.IsMatch(expression.Trim());
 24		}
 25
 26		public static bool IsProjectionExpression(string expression)
 27		{
 28			return s_projection.IsMatch(expression.Trim());
 29		}
 30
 31		public static IList<AggregateExpressionPathItem> BuildAggregatePathItem(ClassMappingDescriptor descriptor, MemberMappingDescriptor member)
 32		{
 33			string firstPart = member.AggregateMappingDescription.PathParts[0];
 34			string targetName = firstPart.StartsWith("$") ? "source" : "";
 35			List<AggregateExpressionPathItem> pathItems = new List<AggregateExpressionPathItem>(3);
 36			Type targetType = descriptor.SourceType;
 37
 38
 39			foreach (string pathPart in member.AggregateMappingDescription.PathParts)
 40			{
 41				if (pathPart.Contains("."))
 42				{
 43					string[] subParts = pathPart.Split('.');
 44					foreach (string subPart in subParts)
 45					{
 46						targetName = AddPathItems(member, pathItems, subPart, targetName, ref targetType);	
 47					}
 48				}
 49				else
 50				{
 51					targetName = AddPathItems(member, pathItems, pathPart, targetName, ref targetType);
 52				}
 53			}
 54			return pathItems;
 55		}
 56
 57		private static string AddPathItems(MemberMappingDescriptor member, List<AggregateExpressionPathItem> pathItems, string pathPart, string targetName, ref Type targetType) {
 58			targetType = GetTargetType(targetType, pathPart.Replace("$", ""));
 59			string objectName = GetCollectionItemName(pathPart);
 60			bool isCollection = IsCollection(targetType);
 61			if(isCollection)
 62				pathItems.Add(new AggregateExpressionPathItem(ToInstanceType(member, targetType), objectName, targetName, pathPart, isCollection));
 63			else
 64				pathItems.Add(new AggregateExpressionPathItem(ToInstanceType(member, targetType), objectName, targetName, pathPart, isCollection));
 65			targetType = ToInstanceType(member, targetType);
 66			targetName = objectName;
 67			return targetName;
 68		}
 69
 70
 71		private static Type GetTargetType(Type type, string memberName)
 72		{
 73			FieldInfo field = type.GetField(memberName, BindingFlags.Public | BindingFlags.Instance);
 74			if (field != null)
 75				return field.FieldType;
 76
 77			PropertyInfo property = type.GetProperty(memberName, BindingFlags.Public | BindingFlags.Instance);
 78			if (property != null)
 79				return property.PropertyType;
 80
 81			throw new OtisException("Expression type can't be deduced"); // todo: msg, test
 82		}
 83
 84		private static bool IsCollection(Type type)
 85		{
 86			return (type.IsArray
 87			        || type.GetInterface(typeof (ICollection<>).FullName) != null
 88			        || typeof (System.Collections.ICollection).IsAssignableFrom(type));
 89		}
 90
 91		private static Type ToInstanceType(MemberMappingDescriptor member, Type type)
 92		{
 93			if(type.IsArray)
 94			{
 95				return type.GetElementType();
 96			}
 97			if(typeof(System.Collections.ICollection).IsAssignableFrom(type))
 98			{
 99				string msg = ErrorBuilder.CantAggregateOverUntypedCollections(member);
100				throw new OtisException(msg);
101			}
102
103			if(type.GetInterface(typeof(ICollection<>).FullName) != null) // generic collection
104			{
105				return type.GetGenericArguments()[0];
106			}
107
108			// simple type
109			return type;
110		}
111
112		private static string GetCollectionItemName(string part)
113		{
114			part = part.Replace("$", "");
115			string itemName = "__" + part.ToLower().Trim();
116			if (itemName.EndsWith("s"))
117				itemName = itemName.Substring(0, itemName.Length - 1);
118			return itemName;
119		}
120
121		public static string NormalizeExpression(string input)
122		{
123			if (ExpressionParser.IsLiteralExpression(input))
124				input = input.Replace('\'', '\"').Substring(1, input.Length - 2);
125
126			return input;			
127		}
128	}
129}