private string BuildPropertyPath(PropertyTraversalPath sourcePath, List <PropertyTraversalPath> parameters, bool targetIsArray) { if (sourcePath == null) { return("source"); } var parameter = GetParameterThatIsSubPath(sourcePath, parameters); var subPath = sourcePath.SubPath(parameter); // TODO - will need to be greatly expanded to handle arrays/collections/choice etc if (subPath == null || !subPath.Any()) { return(parameter.Name); } var propPath = parameter.Name; if (parameter.IsArray && !targetIsArray) { propPath += ".First()"; } foreach (var item in subPath) { propPath += "?." + AppendPropertyPath(item, targetIsArray); } return(propPath); }
public void Resolve(Dictionary <int, TypeMapping> existingTypeMappings, Type rootSourceType, Type rootTargetType, SchemaItem rootSourceSchemaItem, SchemaItem rootTargetSchemaItem, Mapping mapping) { foreach (var itemMapping in mapping.SchemaItemMappings) { if (itemMapping.SourceSchemaItemId.HasValue) { if (itemMapping.SourceSchemaItem.IsRoot) { itemMapping.SourcePath = new PropertyTraversalPath() { RootType = rootSourceType }; } else { itemMapping.SourcePath = PathManipulation.GetClrPropertyPathFromPath(rootSourceType, itemMapping.SourceSchemaItem.Path, 1); } } if (!existingTypeMappings.ContainsKey(itemMapping.TargetSchemaItem.key)) { PropertyTraversalPath targetPath = null; if (!itemMapping.TargetSchemaItem.IsRoot) { targetPath = PathManipulation.GetClrPropertyPathFromPath(rootTargetType, itemMapping.TargetSchemaItem.Path, 1); } existingTypeMappings.Add(itemMapping.TargetSchemaItem.key, new TypeMapping { TargetPath = targetPath, Mappings = new List <SchemaItemMapping>() }); } existingTypeMappings[itemMapping.TargetSchemaItem.key].Mappings.Add(itemMapping); } if (!existingTypeMappings.ContainsKey(rootTargetSchemaItem.key)) { var rootTm = new TypeMapping() { Mappings = new List <SchemaItemMapping>() { new SchemaItemMapping() { SourceSchemaItem = rootSourceSchemaItem, SourceSchemaItemId = rootSourceSchemaItem.key, SourcePath = new PropertyTraversalPath() { RootType = rootSourceType }, TargetSchemaItem = rootTargetSchemaItem, TargetSchemaItemId = rootTargetSchemaItem.key, Action = new SchemaItemMappingAction() { Id = MappingAction.Transform } } } }; existingTypeMappings.Add(rootTargetSchemaItem.key, rootTm); } }
private PropertyTraversalPath GetParameterThatIsSubPath(PropertyTraversalPath sourcePath, List <PropertyTraversalPath> parameters) { var ordered = parameters.Where(a => a.Path != null).OrderByDescending(a => a.Path.Count); foreach (var parameter in ordered) { if (parameter.RootType == sourcePath.RootType && sourcePath.Path.Any(a => a.Property == parameter.Property)) { return(parameter); } } return(parameters.FirstOrDefault(a => a.RootType == sourcePath.RootType)); }
private static PropertyTraversalPath AddTraversal(List <SchemaItem> path, int index, PropertyTraversalPath traversalPath, PropertyInfo prop) { traversalPath.Path.Add(new PropertyTraversal() { Property = prop }); if (index == path.Count - 1) { return(traversalPath); } else { return(GetClrPropertyPathFromPathInternal(prop.PropertyType, path, index + 1, traversalPath)); } }
private static PropertyTraversalPath GetClrPropertyPathFromPathInternal(Type type, List <SchemaItem> path, int index, PropertyTraversalPath traversalPath) { Log("Working out path " + PathAsString(path)); var item = path[index]; var parent = path[index - 1]; if (parent.Occurrance.Max == null) { if (index == path.Count - 1) { return(traversalPath); } else { if (type.IsArray) { return(GetClrPropertyPathFromPathInternal(type.GetElementType(), path, index + 1, traversalPath)); } else { // assume a collection return(GetClrPropertyPathFromPathInternal(type.GetGenericArguments().First(), path, index + 1, traversalPath)); } } } else { var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); if (item.title == ChoiceItemName) { // TODO - assumes the choice element will be named 'item' var prop = props.FirstOrDefault(a => a.Name.Equals("Item", StringComparison.InvariantCultureIgnoreCase)); if (prop != null) { return(AddChoiceTraversal(path, index, traversalPath, prop)); } } else { Log("Looking for property named " + item.title); // "choose one of" == choice. Need to var prop = props.FirstOrDefault(a => a.Name.Equals(item.title, StringComparison.InvariantCultureIgnoreCase)); if (prop != null) { return(AddTraversal(path, index, traversalPath, prop)); } // if there are clashes NJsonSchema adds a '1' etc to the end of the type name // TODO - consider searching for more numbers? prop = props.FirstOrDefault(a => a.Name.Equals(item.title + "1", StringComparison.InvariantCultureIgnoreCase)); if (prop != null) { return(AddTraversal(path, index, traversalPath, prop)); } } throw new InvalidOperationException("traversal not found for " + item.title); } }
private static PropertyTraversalPath AddChoiceTraversal(List <SchemaItem> path, int index, PropertyTraversalPath traversalPath, PropertyInfo prop) { var attribs = Attribute.GetCustomAttributes(prop, typeof(XmlElementAttribute)).Select(a => (XmlElementAttribute)a).ToList(); var child = path[index + 1]; var attrib = attribs.First(a => a.ElementName == child.title); traversalPath.Path.Add(new PropertyTraversal() { Property = prop, ChoiceInfo = new ChoiceInfo { ElementAttribute = attrib } }); if (index == path.Count - 2) { return(traversalPath); } else { // +2 here because we've effectively skipped over the 'choice' element and gone straight to the child return(GetClrPropertyPathFromPathInternal(attrib.Type, path, index + 2, traversalPath)); } }