public void Mapping_Fails_For_Duplicate_Projection() { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.OwnerType = typeof(AttributedUserDTO); desc.Type = typeof(string); desc.Member = "FullName"; desc.IsArray = false; desc.IsList = false; try { List <ProjectionItem> items = new List <ProjectionItem>(); items.Add(new ProjectionItem("source", "target_1")); items.Add(new ProjectionItem("source", "target_2")); ProjectionBuilder.Build(desc, items); } catch (OtisException e) { if (e.Message.Contains("Invalid projection 'source => target_2'. 'source' is already mapped to '\"target_1\"'")) { return; // success } } Assert.Fail("Tested method didn't throw an exception!"); }
internal static ProjectionInfo BuildProjections(MemberMappingDescriptor desc, XmlNodeList projections) { if (projections.Count < 1) return new ProjectionInfo(); List<ProjectionItem> projectionItems = new List<ProjectionItem>(3); foreach (XmlNode node in projections) { // no check for existance, that is done with schema string to = GetAttributeValue(node.Attributes["to"]); if (to == string.Empty) { string message = ErrorBuilder.EmptyToAttributeInXmlError(desc, node.InnerXml); throw new OtisException(message); } // if 'from' is missing, it is assumed to be same as 'to' string from = GetAttributeValue(node.Attributes["from"], to); projectionItems.Add( new ProjectionItem( ExpressionParser.NormalizeExpression(from), ExpressionParser.NormalizeExpression(to))); } return ProjectionBuilder.Build(desc,projectionItems); }
public void Setup() { m_desc = new MemberMappingDescriptor(); m_desc.Member = "Gender"; m_desc.OwnerType = typeof(XmlUserDTO); m_desc.Type = typeof(Gender); }
private static CodeStatement[] CreateProjectionMapping(MemberMappingDescriptor member) { StringBuilder snippet = new StringBuilder(); snippet.AppendLine(string.Format("switch({0}) {{", UnwindExpression(member.Expression))); foreach (ProjectionItem item in member.Projections.Items) { string resultExpression; if (member.HasFormatting) { resultExpression = string.Format("string.Format(\"{0}\", {1})", member.Format, item.To); } else { resultExpression = item.To; } snippet.AppendLine(string.Format(" case {0}: target.{1} = {2}; break;", item.From, member.Member, resultExpression)); } snippet.AppendLine("}"); CodeStatementCollection coll = new CodeStatementCollection(); coll.Add(new CodeSnippetExpression(snippet.ToString())); return(new CodeStatement[1] { coll[0] }); }
private static CodeStatement[] CreateAssemblerMapping(MemberMappingDescriptor member) { string expression = UnwindExpression(member.Expression); if (member.Type.IsPrimitive) { return(new CodeStatement[] { new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), new CodeSnippetExpression(expression)) }); } CodeMethodInvokeExpression transform = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Transform", new CodeVariableReferenceExpression("target." + member.Member), new CodeArgumentReferenceExpression(expression) ); if (member.HasNullValue) { transform.Parameters.Add(new CodeSnippetExpression(member.NullValue.ToString())); } CodeStatement st = new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), transform); return(new CodeStatement[] { st }); }
public void Collect_Fails_On_Noncollection_Target() { CollectFunction fn = new CollectFunction(); MemberMappingDescriptor member = new MemberMappingDescriptor(); member.OwnerType = typeof(AttributedUserDTO); member.Type = typeof(string); member.Member = "FullName"; member.IsArray = false; member.IsList = false; member.Expression = "sum:$Projects/Tasks"; ClassMappingDescriptor desc = new ClassMappingDescriptor(); desc.SourceType = typeof(User); AggregateFunctionContext ctxt = new AggregateFunctionContext(member, desc, null, "", null); try { fn.GetInitializationStatements(ctxt); } catch (OtisException e) { if (e.Message.Contains("Target member 'FullName' for 'collect' aggregate function must be an array or a collection")) { return; // success } } Assert.Fail("Tested method didn't throw an exception!"); }
private static string GetPath(ClassMappingDescriptor descriptor, MemberMappingDescriptor member) { // todo: optimize - don't do this for every member, this is also done in AggregateFunctionContext ctor IList <AggregateExpressionPathItem> pathItems = ExpressionParser.BuildAggregatePathItem(descriptor, member); bool isLastItemCollection = pathItems[pathItems.Count - 1].IsCollection; string path = member.Expression; int pos = path.IndexOf(':'); if (pos >= 0) { path = path.Substring(pos + 1); } if (!isLastItemCollection) { pos = path.LastIndexOf('/'); if (pos >= 0) { path = path.Substring(0, pos); } } return(path); }
private static void CopyMemberDescriptors(ClassMappingDescriptor from, ClassMappingDescriptor to) { foreach (MemberMappingDescriptor fromMember in from.MemberDescriptors) { // check if the member mapping is overriden in the derived class - do // not copy in that case bool overriden = false; foreach (MemberMappingDescriptor derivedMember in to.MemberDescriptors) { if (!fromMember.Member.Equals(derivedMember.Member)) { continue; } overriden = true; break; } if (overriden) { continue; } MemberMappingDescriptor toMember = new MemberMappingDescriptor(fromMember); toMember.OwnerType = to.TargetType; // check if the member is visible in the derived type MemberInfo member = FindMember(to.TargetType, toMember.Member); if (member != null) { to.MemberDescriptors.Add(toMember); } } }
private static CodeStatement[] CreateAssemblerMapping(MemberMappingDescriptor member) { string expression = UnwindExpression(member.Expression); if(member.Type.IsPrimitive) { return new CodeStatement[] { new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), new CodeSnippetExpression(expression)) }; } CodeMethodInvokeExpression transform = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Transform", new CodeVariableReferenceExpression("target." + member.Member), new CodeArgumentReferenceExpression(expression) ); if(member.HasNullValue) { transform.Parameters.Add(new CodeSnippetExpression(member.NullValue.ToString())); } CodeStatement st = new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), transform); return new CodeStatement[] { st }; }
internal static ProjectionInfo BuildProjections(MemberMappingDescriptor desc, XmlNodeList projections) { if (projections.Count < 1) { return(new ProjectionInfo()); } List <ProjectionItem> projectionItems = new List <ProjectionItem>(3); foreach (XmlNode node in projections) { // no check for existance, that is done with schema string to = GetAttributeValue(node.Attributes["to"]); if (to == string.Empty) { string message = ErrorBuilder.EmptyToAttributeInXmlError(desc, node.InnerXml); throw new OtisException(message); } // if 'from' is missing, it is assumed to be same as 'to' string from = GetAttributeValue(node.Attributes["from"], to); projectionItems.Add( new ProjectionItem( ExpressionParser.NormalizeExpression(from), ExpressionParser.NormalizeExpression(to))); } return(ProjectionBuilder.Build(desc, projectionItems)); }
private AggregateFunctionContext CreateMemberContext(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, FunctionMap functionMap) { Type implementationType = functionMap.GetTypeForFunction(member.AggregateMappingDescription.FunctionName); string functionObjectName = string.Format("_{0}_to_{1}_Fn_", member.AggregateMappingDescription.FunctionObject, member.Member); if (implementationType.IsGenericType) { if (member.IsArray || member.IsList) { Type instanceType = member.IsArray ? member.AggregateMappingDescription.TargetType.GetElementType() : member.AggregateMappingDescription.TargetType.GetGenericArguments()[0]; implementationType = implementationType.MakeGenericType(instanceType); } else { implementationType = implementationType.MakeGenericType(member.AggregateMappingDescription.TargetType); } } IAggregateFunctionCodeGenerator generator = GetGeneratorImpl(implementationType, member); return new AggregateFunctionContext(member, descriptor, implementationType, functionObjectName, generator); }
private static void CheckDescription <Target, Source>(ClassMappingDescriptor desc) { Assert.AreEqual(typeof(Target), desc.TargetType); Assert.AreEqual(typeof(Source), desc.SourceType); Assert.AreEqual("Otis.Tests.Util.Convert", desc.MappingHelper); Assert.AreEqual(8, desc.MemberDescriptors.Count); MemberMappingDescriptor member = null; member = Helpers.FindMember(desc.MemberDescriptors, "Id"); Assert.AreEqual("$Id", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(int), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "Age"); Assert.AreEqual("$Age", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(int), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "UserName"); Assert.AreEqual("$UserName.ToUpper()", member.Expression); Assert.AreEqual("\"[unknown]\"", member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(string), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "FullName"); Assert.AreEqual("$FirstName + \" \" + $LastName", member.Expression); Assert.AreEqual("\"MISSING_NAME_PART\"", member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(string), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "Title"); Assert.AreEqual("\"Mr.\" + $FirstName + \" \" + $LastName", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(string), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "ProjectCount"); Assert.AreEqual("$Projects.Count", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(int), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "Gender"); Assert.AreEqual(2, member.Projections.Count); Assert.AreEqual("Otis.Tests.Gender.Male", member.Projections["\"M\""]); Assert.AreEqual("Otis.Tests.Gender.Female", member.Projections["\"W\""]); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(Otis.Tests.Gender), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "GenderCode"); Assert.AreEqual(2, member.Projections.Count); Assert.AreEqual("\"M\"", member.Projections["\"M\""]); Assert.AreEqual("\"W\"", member.Projections["\"W\""]); }
public void Formatting_Is_Detected_In_Assembly_Mapping() { IMappingDescriptorProvider provider = ProviderFactory.FromType(typeof(UserDTO)); ClassMappingDescriptor desc = provider.ClassDescriptors[0]; MemberMappingDescriptor member = Helpers.FindMember(desc.MemberDescriptors, "BirthDay"); Assert.IsTrue(member.HasFormatting); Assert.AreEqual("{0:D}", member.Format); }
private Type GetSourceItemType(IList <AggregateExpressionPathItem> items, MemberMappingDescriptor member) { if (items == null || items.Count < 1) { string msg = ErrorBuilder.InvalidAggregatePathError(member); throw new OtisException(msg); } return(items[items.Count - 1].Type); }
private static string GetNullablePartsCheckExpression(MemberMappingDescriptor member) { StringBuilder sb = new StringBuilder(20); foreach (string nullablePart in member.NullableParts) { sb.Append(nullablePart.Replace("$", "source.")); sb.Append(" == null || "); } return(sb.ToString(0, sb.Length - 4)); }
public void Formatting_Is_Detected_In_Xml_Mapping() { IMappingDescriptorProvider provider = ProviderFactory.FromXmlFile("XmlMappings\\mappings.xml"); Assert.AreEqual(2, provider.ClassDescriptors.Count); ClassMappingDescriptor desc = provider.ClassDescriptors[1]; MemberMappingDescriptor member = Helpers.FindMember(desc.MemberDescriptors, "BirthDay"); Assert.IsTrue(member.HasFormatting); Assert.AreEqual("{0:D}", member.Format); }
internal static ProjectionInfo GetProjections(MemberMappingDescriptor desc, string projection) { string normalizedProjection = ExpressionParser.NormalizeExpression(projection); normalizedProjection = normalizedProjection.Trim(';', ' '); if (!ExpressionParser.IsProjectionExpression(normalizedProjection)) { // use original string in message to make it easier to find the attribute string message = ErrorBuilder.InvalidProjectionStringError(desc, projection); throw new OtisException(message); } IList<ProjectionItem> projectionItems = SplitProjectionItems(normalizedProjection); return ProjectionBuilder.Build(desc, projectionItems); }
public override IEnumerable <CodeStatement> GetInitializationStatements(AggregateFunctionContext context) { MemberMappingDescriptor member = context.Member; Type resultType; Type instanceType; bool isSimpleMapping = false; if (member.IsArray || member.IsList) { instanceType = member.IsArray ? member.AggregateMappingDescription.TargetType.GetElementType() : member.AggregateMappingDescription.TargetType.GetGenericArguments()[0]; resultType = typeof(List <>).MakeGenericType(instanceType); if (!instanceType.IsPrimitive && instanceType != typeof(string)) { m_expression = string.Format("{{0}}.Add({0}.AssembleFrom({{1}}));", GetAssemblerName(context)); } else { m_expression = "{0}.Add({1});"; isSimpleMapping = true; } } else { string msg = ErrorBuilder.CantAggregateOverNoncollectionError(member, "collect"); throw new OtisException(msg); //todo: test } m_isArray = member.IsArray; List <CodeStatement> statements = new List <CodeStatement>(); CodeExpression[] parameters = new CodeExpression[0]; CodeStatement st = new CodeVariableDeclarationStatement(resultType, context.FunctionObjectName, new CodeObjectCreateExpression(resultType, parameters)); statements.Add(st); if (!isSimpleMapping) { st = new CodeVariableDeclarationStatement( string.Format("IAssembler<{0}, {1}>", TypeHelper.GetTypeDefinition(instanceType), TypeHelper.GetTypeDefinition(context.SourceItemType)), GetAssemblerName(context), new CodeSnippetExpression("this")); statements.Add(st); } return(statements); }
internal static ProjectionInfo GetProjections(MemberMappingDescriptor desc, string projection) { string normalizedProjection = ExpressionParser.NormalizeExpression(projection); normalizedProjection = normalizedProjection.Trim(';', ' '); if (!ExpressionParser.IsProjectionExpression(normalizedProjection)) { // use original string in message to make it easier to find the attribute string message = ErrorBuilder.InvalidProjectionStringError(desc, projection); throw new OtisException(message); } IList <ProjectionItem> projectionItems = SplitProjectionItems(normalizedProjection); return(ProjectionBuilder.Build(desc, projectionItems)); }
public AggregateFunctionContext(MemberMappingDescriptor member, ClassMappingDescriptor descriptor, Type implementationType, string functionObjectName, IAggregateFunctionCodeGenerator generator) { m_member = member; m_generator = generator; m_functionObjectName = functionObjectName; m_implementationType = implementationType; m_descriptor = descriptor; m_pathItems = ExpressionParser.BuildAggregatePathItem(descriptor, member); m_sourceItem = m_pathItems[m_pathItems.Count - 1]; }
private static CodeStatement[] CreateListMappingStatements(MemberMappingDescriptor member) { string expression = member.Expression.Replace("$", "source."); CodeStatement[] statements = new CodeStatement[1]; CodeMethodInvokeExpression transform = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "TransformToList", new CodeVariableReferenceExpression("target." + member.Member), new CodeArgumentReferenceExpression(expression) ); statements[0] = new CodeExpressionStatement(transform); return(statements); }
private static CodeStatement[] CreateArrayMappingStatements(MemberMappingDescriptor member) { string expression = member.Expression.Replace("$", "source."); CodeStatement[] statements = new CodeStatement[1]; statements[0] = new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), new CodeMethodInvokeExpression( new CodeThisReferenceExpression(), "TransformToArray", new CodeVariableReferenceExpression("target." + member.Member), new CodeArgumentReferenceExpression(expression) )); return statements; }
private static string ExpandProjectionTarget(MemberMappingDescriptor desc, ProjectionItem projectionItem) { if (desc.Type == typeof(string)) return ExpandString(projectionItem.To); if (desc.Type.IsEnum) { string expanded = ExpandEnum(desc.Type, projectionItem.To); if(expanded == "") // no match { string error = ErrorBuilder.EnumValueDoesntExistError(desc, projectionItem); throw new OtisException(error); } return expanded; } return projectionItem.To; }
private static string AddPathItems(MemberMappingDescriptor member, List <AggregateExpressionPathItem> pathItems, string pathPart, string targetName, ref Type targetType) { targetType = GetTargetType(targetType, pathPart.Replace("$", "")); string objectName = GetCollectionItemName(pathPart); bool isCollection = IsCollection(targetType); if (isCollection) { pathItems.Add(new AggregateExpressionPathItem(ToInstanceType(member, targetType), objectName, targetName, pathPart, isCollection)); } else { pathItems.Add(new AggregateExpressionPathItem(ToInstanceType(member, targetType), objectName, targetName, pathPart, isCollection)); } targetType = ToInstanceType(member, targetType); targetName = objectName; return(targetName); }
public void Nullable_parts_extraction() { MemberMappingDescriptor member = new MemberMappingDescriptor(); member.Expression = "$FirstName"; Assert.IsTrue(member.HasNullableParts); Assert.AreEqual(1, member.NullableParts.Count); Assert.AreEqual("$FirstName", member.NullableParts[0]); member.Expression = "$FirstName.ToUpper()"; Assert.IsTrue(member.HasNullableParts); Assert.AreEqual(1, member.NullableParts.Count); Assert.AreEqual("$FirstName", member.NullableParts[0]); member.Expression = "$FirstName.ToUpper(true)"; Assert.IsTrue(member.HasNullableParts); Assert.AreEqual(1, member.NullableParts.Count); Assert.AreEqual("$FirstName", member.NullableParts[0]); member.Expression = "$ToUpper()"; Assert.IsTrue(member.HasNullableParts); Assert.AreEqual(1, member.NullableParts.Count); Assert.AreEqual("$ToUpper()", member.NullableParts[0]); member.Expression = "$ToUpper().ToLower()"; Assert.IsTrue(member.HasNullableParts); Assert.AreEqual(1, member.NullableParts.Count); Assert.AreEqual("$ToUpper()", member.NullableParts[0]); member.Expression = "$ToUpper(true)"; Assert.IsTrue(member.HasNullableParts); Assert.AreEqual(1, member.NullableParts.Count); Assert.AreEqual("$ToUpper(true)", member.NullableParts[0]); member.Expression = "$FirstName + $LastName"; Assert.IsTrue(member.HasNullableParts); Assert.AreEqual(2, member.NullableParts.Count); Assert.AreEqual("$FirstName", member.NullableParts[0]); Assert.AreEqual("$LastName", member.NullableParts[1]); member.Expression = "tmp.GetSomeValue"; Assert.IsFalse(member.HasNullableParts); Assert.AreEqual(0, member.NullableParts.Count); }
public static ProjectionInfo Build(MemberMappingDescriptor desc, IList <ProjectionItem> projectionItems) { ProjectionInfo projectionInfo = new ProjectionInfo(); foreach (ProjectionItem projectionItem in projectionItems) { string from = projectionItem.From; if (projectionInfo.ContainsKey(from)) { string error = ErrorBuilder.DuplicateProjectionError(desc, projectionItem, projectionInfo[from]); throw new OtisException(error); } string expandedTo = ExpandProjectionTarget(desc, projectionItem); projectionInfo[from] = expandedTo; } return(projectionInfo); }
public static ProjectionInfo Build(MemberMappingDescriptor desc, IList<ProjectionItem> projectionItems) { ProjectionInfo projectionInfo = new ProjectionInfo(); foreach (ProjectionItem projectionItem in projectionItems) { string from = projectionItem.From; if(projectionInfo.ContainsKey(from)) { string error = ErrorBuilder.DuplicateProjectionError(desc, projectionItem, projectionInfo[from]); throw new OtisException(error); } string expandedTo = ExpandProjectionTarget(desc, projectionItem); projectionInfo[from] = expandedTo; } return projectionInfo; }
private static Type ToInstanceType(MemberMappingDescriptor member, Type type) { if (type.IsArray) { return(type.GetElementType()); } if (typeof(System.Collections.ICollection).IsAssignableFrom(type)) { string msg = ErrorBuilder.CantAggregateOverUntypedCollections(member); throw new OtisException(msg); } if (type.GetInterface(typeof(ICollection <>).FullName) != null) // generic collection { return(type.GetGenericArguments()[0]); } // simple type return(type); }
private static string ExpandProjectionTarget(MemberMappingDescriptor desc, ProjectionItem projectionItem) { if (desc.Type == typeof(string)) { return(ExpandString(projectionItem.To)); } if (desc.Type.IsEnum) { string expanded = ExpandEnum(desc.Type, projectionItem.To); if (expanded == "") // no match { string error = ErrorBuilder.EnumValueDoesntExistError(desc, projectionItem); throw new OtisException(error); } return(expanded); } return(projectionItem.To); }
public void Mapping_Fails_For_Duplicate_Projection() { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.OwnerType = typeof(AttributedUserDTO); desc.Type = typeof(string); desc.Member = "FullName"; desc.IsArray = false; desc.IsList = false; try { List<ProjectionItem> items = new List<ProjectionItem>(); items.Add(new ProjectionItem("source", "target_1")); items.Add(new ProjectionItem("source", "target_2")); ProjectionBuilder.Build(desc, items); } catch (OtisException e) { if (e.Message.Contains("Invalid projection 'source => target_2'. 'source' is already mapped to '\"target_1\"'")) return; // success } Assert.Fail("Tested method didn't throw an exception!"); }
private static CodeStatement[] CreateSimpleMapping(MemberMappingDescriptor member) { string expression = UnwindExpression(member.Expression); if (member.Type == typeof(string)) { if (member.HasFormatting) { expression = string.Format("string.Format(\"{0}\", {1})", member.Format, expression); } else { expression = string.Format("({0}).ToString()", expression); } } CodeSnippetExpression exp = new CodeSnippetExpression(expression); CodeStatement st = new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), exp); return(new CodeStatement[] { st }); }
private MemberMappingDescriptor CreateMemberDescriptor(ClassMappingDescriptor classDesc, XmlNode node) { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.Member = GetAttributeValue(node.Attributes["name"]); desc.Expression = GetAttributeValue(node.Attributes["expression"], "$" + desc.Member); desc.NullValue = GetAttributeValue(node.Attributes["nullValue"]); desc.Format = GetAttributeValue(node.Attributes["format"]); desc.OwnerType = classDesc.TargetType; MemberInfo member = FindMember(classDesc.TargetType, desc.Member); if (member == null) { string msg = string.Format(Errors.MemberNotFound, desc.Member, TypeHelper.GetTypeDefinition(classDesc.TargetType)); throw new OtisException(msg); } desc.Type = GetTargetType(member); if (desc.HasFormatting && desc.Type != typeof(string)) { string msg = string.Format(Errors.FormattingAppliedOnNonStringMember, TypeHelper.GetTypeDefinition(classDesc.TargetType), desc.Member, TypeHelper.GetTypeDefinition(desc.Type)); throw new OtisException(msg); } desc.IsArray = desc.Type.IsArray; desc.IsList = (typeof(ICollection).IsAssignableFrom(desc.Type)) || desc.Type.GetInterface(typeof(ICollection <>).FullName) != null; XmlNodeList projections = node.SelectNodes("default:map", m_nsMgr); desc.Projections = BuildProjections(desc, projections); return(desc); }
public void Projection_Mapping_Fails_For_Nonexisting_Enum_Value() { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.OwnerType = typeof(AttributedUserDTO); desc.Type = typeof(Gender); desc.Member = "Gender"; desc.IsArray = false; desc.IsList = false; try { List <ProjectionItem> items = new List <ProjectionItem>(); items.Add(new ProjectionItem("X", "Undefined")); ProjectionBuilder.Build(desc, items); } catch (OtisException e) { if (e.Message.Contains("Invalid projection 'X => Undefined'. Value 'Undefined' is not defined in 'Otis.Tests.Gender' enumeration")) { return; // success } } Assert.Fail("Tested method didn't throw an exception!"); }
private Type GetSourceItemType(IList<AggregateExpressionPathItem> items, MemberMappingDescriptor member) { if (items == null || items.Count < 1) { string msg = ErrorBuilder.InvalidAggregatePathError(member); throw new OtisException(msg); } return items[items.Count - 1].Type; }
private static CodeStatement[] CreateSimpleMapping(MemberMappingDescriptor member) { string expression = UnwindExpression(member.Expression); if(member.Type == typeof(string)) { if (member.HasFormatting) expression = string.Format("string.Format(\"{0}\", {1})", member.Format, expression); else expression = string.Format("({0}).ToString()", expression); } CodeSnippetExpression exp = new CodeSnippetExpression(expression); CodeStatement st = new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), exp); return new CodeStatement[] { st }; }
private static void CopyMemberDescriptors(ClassMappingDescriptor from, ClassMappingDescriptor to) { foreach(MemberMappingDescriptor fromMember in from.MemberDescriptors) { // check if the member mapping is overriden in the derived class - do // not copy in that case bool overriden = false; foreach(MemberMappingDescriptor derivedMember in to.MemberDescriptors) { if (!fromMember.Member.Equals(derivedMember.Member)) continue; overriden = true; break; } if (overriden) continue; MemberMappingDescriptor toMember = new MemberMappingDescriptor(fromMember); toMember.OwnerType = to.TargetType; // check if the member is visible in the derived type MemberInfo member = FindMember(to.TargetType, toMember.Member); if (member != null) { to.MemberDescriptors.Add(toMember); } } }
private IAggregateFunctionCodeGenerator GetGeneratorImpl(Type implementationType, MemberMappingDescriptor member) { Type[] interfaces = implementationType.GetInterfaces(); foreach (Type itf in interfaces) // first check if it has its own implementation of IAggregateFunctionCodeGenerator { if (itf == typeof (IAggregateFunctionCodeGenerator)) return Activator.CreateInstance(implementationType, true) as IAggregateFunctionCodeGenerator; } foreach (Type itf in interfaces) // now check if it only implement IAggregateFunction { if (itf.IsGenericType && itf.GetGenericTypeDefinition() == typeof(IAggregateFunction<>)) return new DefaultAggregateFunctionCodeGenerator(); } string msg = ErrorBuilder.InvalidAggregatePathError(member); throw new OtisException(msg); // test }
private MemberMappingDescriptor CreateMemberDescriptor(ClassMappingDescriptor classDesc, XmlNode node) { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.Member = GetAttributeValue(node.Attributes["name"]); desc.Expression = GetAttributeValue(node.Attributes["expression"], "$" + desc.Member); desc.NullValue = GetAttributeValue(node.Attributes["nullValue"]); desc.Format = GetAttributeValue(node.Attributes["format"]); desc.OwnerType = classDesc.TargetType; MemberInfo member = FindMember(classDesc.TargetType, desc.Member); if(member == null) { string msg = string.Format(Errors.MemberNotFound, desc.Member, TypeHelper.GetTypeDefinition(classDesc.TargetType)); throw new OtisException(msg); } desc.Type = GetTargetType(member); if(desc.HasFormatting && desc.Type != typeof(string)) { string msg = string.Format(Errors.FormattingAppliedOnNonStringMember, TypeHelper.GetTypeDefinition(classDesc.TargetType), desc.Member, TypeHelper.GetTypeDefinition(desc.Type)); throw new OtisException(msg); } desc.IsArray = desc.Type.IsArray; desc.IsList = (typeof (ICollection).IsAssignableFrom(desc.Type)) || desc.Type.GetInterface(typeof(ICollection<>).FullName) != null; XmlNodeList projections = node.SelectNodes("default:map", m_nsMgr); desc.Projections = BuildProjections(desc, projections); return desc; }
private static string GetNullablePartsCheckExpression(MemberMappingDescriptor member) { StringBuilder sb = new StringBuilder(20); foreach (string nullablePart in member.NullableParts) { sb.Append(nullablePart.Replace("$", "source.")); sb.Append(" == null || "); } return sb.ToString(0, sb.Length - 4); }
private static CodeStatement[] CreateNonAggregateMappingStatements(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, CodeGeneratorContext context) { if (member.Projections.Count > 0) { return(CreateProjectionMapping(member)); } if (member.Type == typeof(string) || member.Type.IsPrimitive) { return(CreateSimpleMapping(member)); } if (member.IsArray) { return(CreateArrayMappingStatements(member)); } if (member.IsList) { return(CreateListMappingStatements(member)); } return(CreateAssemblerMapping(member)); }
private static MemberMappingDescriptor CreateMemberMapping(ClassMappingDescriptor classDesc, MemberInfo member) { MemberMappingDescriptor desc = new MemberMappingDescriptor(); object[] attrs = member.GetCustomAttributes(typeof(MapAttribute), false); MapAttribute attr = (MapAttribute) attrs[0]; // todo: assert (should be exactly 1) + test desc.Member = member.Name; desc.Expression = attr.Expression ?? "$" + desc.Member; if (attr.NullValue is string) desc.NullValue = "\"" + attr.NullValue.ToString().Trim('"') + "\""; else if(attr.NullValue != null) desc.NullValue = attr.NullValue.ToString(); else desc.NullValue = null; desc.Format = attr.Format; desc.OwnerType = classDesc.TargetType; if(member.MemberType == MemberTypes.Property) { PropertyInfo p = (PropertyInfo)member; desc.Type = p.PropertyType; } else { FieldInfo f = (FieldInfo)member; desc.Type = f.FieldType; } if(desc.HasFormatting && desc.Type != typeof(string)) { string msg = string.Format(Errors.FormattingAppliedOnNonStringMember, TypeHelper.GetTypeDefinition(classDesc.TargetType), desc.Member, TypeHelper.GetTypeDefinition(desc.Type)); throw new OtisException(msg); } if(desc.Type.IsArray) { desc.IsArray = true; } else if (typeof(ICollection).IsAssignableFrom(desc.Type) || desc.Type.GetInterface(typeof(ICollection<>).FullName) != null) { desc.IsList = true; } if(attr.HasProjection) { desc.Projections = GetProjections(desc, attr.Projection); } return desc; }
private IAggregateFunctionCodeGenerator GetGeneratorImpl(Type implementationType, MemberMappingDescriptor member) { Type[] interfaces = implementationType.GetInterfaces(); foreach (Type itf in interfaces) // first check if it has its own implementation of IAggregateFunctionCodeGenerator { if (itf == typeof(IAggregateFunctionCodeGenerator)) { return(Activator.CreateInstance(implementationType, true) as IAggregateFunctionCodeGenerator); } } foreach (Type itf in interfaces) // now check if it only implement IAggregateFunction { if (itf.IsGenericType && itf.GetGenericTypeDefinition() == typeof(IAggregateFunction <>)) { return(new DefaultAggregateFunctionCodeGenerator()); } } string msg = ErrorBuilder.InvalidAggregatePathError(member); throw new OtisException(msg); // test }
public void Projection_Mapping_Fails_For_Nonexisting_Enum_Value() { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.OwnerType = typeof(AttributedUserDTO); desc.Type = typeof(Gender); desc.Member = "Gender"; desc.IsArray = false; desc.IsList = false; try { List<ProjectionItem> items = new List<ProjectionItem>(); items.Add(new ProjectionItem("X", "Undefined")); ProjectionBuilder.Build(desc, items); } catch (OtisException e) { if (e.Message.Contains("Invalid projection 'X => Undefined'. Value 'Undefined' is not defined in 'Otis.Tests.Gender' enumeration")) return; // success } Assert.Fail("Tested method didn't throw an exception!"); }
private AggregateFunctionContext CreateMemberContext(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, FunctionMap functionMap) { Type implementationType = functionMap.GetTypeForFunction(member.AggregateMappingDescription.FunctionName); string functionObjectName = string.Format("_{0}_to_{1}_Fn_", member.AggregateMappingDescription.FunctionObject, member.Member); if (implementationType.IsGenericType) { if (member.IsArray || member.IsList) { Type instanceType = member.IsArray ? member.AggregateMappingDescription.TargetType.GetElementType() : member.AggregateMappingDescription.TargetType.GetGenericArguments()[0]; implementationType = implementationType.MakeGenericType(instanceType); } else { implementationType = implementationType.MakeGenericType(member.AggregateMappingDescription.TargetType); } } IAggregateFunctionCodeGenerator generator = GetGeneratorImpl(implementationType, member); return(new AggregateFunctionContext(member, descriptor, implementationType, functionObjectName, generator)); }
public static IList <AggregateExpressionPathItem> BuildAggregatePathItem(ClassMappingDescriptor descriptor, MemberMappingDescriptor member) { string firstPart = member.AggregateMappingDescription.PathParts[0]; string targetName = firstPart.StartsWith("$") ? "source" : ""; List <AggregateExpressionPathItem> pathItems = new List <AggregateExpressionPathItem>(3); Type targetType = descriptor.SourceType; foreach (string pathPart in member.AggregateMappingDescription.PathParts) { if (pathPart.Contains(".")) { string[] subParts = pathPart.Split('.'); foreach (string subPart in subParts) { targetName = AddPathItems(member, pathItems, subPart, targetName, ref targetType); } } else { targetName = AddPathItems(member, pathItems, pathPart, targetName, ref targetType); } } return(pathItems); }
private static MemberMappingDescriptor CreateMemberMapping(ClassMappingDescriptor classDesc, MemberInfo member) { MemberMappingDescriptor desc = new MemberMappingDescriptor(); object[] attrs = member.GetCustomAttributes(typeof(MapAttribute), false); MapAttribute attr = (MapAttribute)attrs[0]; // todo: assert (should be exactly 1) + test desc.Member = member.Name; desc.Expression = attr.Expression ?? "$" + desc.Member; if (attr.NullValue is string) { desc.NullValue = "\"" + attr.NullValue.ToString().Trim('"') + "\""; } else if (attr.NullValue != null) { desc.NullValue = attr.NullValue.ToString(); } else { desc.NullValue = null; } desc.Format = attr.Format; desc.OwnerType = classDesc.TargetType; if (member.MemberType == MemberTypes.Property) { PropertyInfo p = (PropertyInfo)member; desc.Type = p.PropertyType; } else { FieldInfo f = (FieldInfo)member; desc.Type = f.FieldType; } if (desc.HasFormatting && desc.Type != typeof(string)) { string msg = string.Format(Errors.FormattingAppliedOnNonStringMember, TypeHelper.GetTypeDefinition(classDesc.TargetType), desc.Member, TypeHelper.GetTypeDefinition(desc.Type)); throw new OtisException(msg); } if (desc.Type.IsArray) { desc.IsArray = true; } else if (typeof(ICollection).IsAssignableFrom(desc.Type) || desc.Type.GetInterface(typeof(ICollection <>).FullName) != null) { desc.IsList = true; } if (attr.HasProjection) { desc.Projections = GetProjections(desc, attr.Projection); } return(desc); }
private static string GetPath(ClassMappingDescriptor descriptor, MemberMappingDescriptor member) { // todo: optimize - don't do this for every member, this is also done in AggregateFunctionContext ctor IList<AggregateExpressionPathItem> pathItems = ExpressionParser.BuildAggregatePathItem(descriptor, member); bool isLastItemCollection = pathItems[pathItems.Count - 1].IsCollection; string path = member.Expression; int pos = path.IndexOf(':'); if (pos >= 0) path = path.Substring(pos + 1); if (!isLastItemCollection) { pos = path.LastIndexOf('/'); if (pos >= 0) path = path.Substring(0, pos); } return path; }
private static CodeStatement[] CreateNonAggregateMappingStatements(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, CodeGeneratorContext context) { if (member.Projections.Count > 0) return CreateProjectionMapping(member); if (member.Type == typeof(string) || member.Type.IsPrimitive) return CreateSimpleMapping(member); if (member.IsArray) return CreateArrayMappingStatements(member); if (member.IsList) return CreateListMappingStatements(member); return CreateAssemblerMapping(member); }
private static CodeStatement[] CreateProjectionMapping(MemberMappingDescriptor member) { StringBuilder snippet = new StringBuilder(); snippet.AppendLine(string.Format("switch({0}) {{", UnwindExpression(member.Expression))); foreach (ProjectionItem item in member.Projections.Items) { string resultExpression; if(member.HasFormatting) resultExpression = string.Format("string.Format(\"{0}\", {1})", member.Format, item.To); else resultExpression = item.To; snippet.AppendLine(string.Format(" case {0}: target.{1} = {2}; break;", item.From, member.Member, resultExpression)); } snippet.AppendLine("}"); CodeStatementCollection coll = new CodeStatementCollection(); coll.Add(new CodeSnippetExpression(snippet.ToString())); return new CodeStatement[1] { coll[0] }; }