/// <summary> /// Reflection based recursive method to populate a type with graph node values /// </summary> private object ConvertGraphToTypedObject(LabelledTreeNode <object, Term> objectGraph, Type type) { if (objectGraph.Children.Count == 0) { if (type.GetTypeInfo().IsAssignableFrom(objectGraph.Value.GetType())) { return(objectGraph.Value); } else { throw new InvalidCastException(string.Format("Cannot cast a {0} to a {1}", objectGraph.Value.GetType(), type)); } } //here we use the fact that expansion types inherit from Resource var obj = Activator.CreateInstance(type, new[] { objectGraph.Value }); foreach (var member in type.GetRuntimeProperties()) { var memberAttribute = member.GetCustomAttribute <PropertyBindAttribute>(); if (memberAttribute != null) { var memberObjectGraphCollection = objectGraph.Descend(memberAttribute.Property); if (member.PropertyType.IsListType()) { var typedList = Activator.CreateInstance(member.PropertyType); var addMethod = member.PropertyType.GetRuntimeMethod("Add", new Type[] { member.PropertyType.GenericTypeArguments[0] }); foreach (var memberObjectGraph in memberObjectGraphCollection) { addMethod.Invoke(typedList, new[] { ConvertGraphToTypedObject(memberObjectGraph, member.PropertyType.GenericTypeArguments[0]) }); } member.SetValue(obj, typedList); } else { LabelledTreeNode <object, Term> memberObjectGraph = null; try { memberObjectGraph = memberObjectGraphCollection.Single(); } catch (Exception) { throw new InvalidOperationException(string.Format("The type {0} declared a non collecton property {1} but more than one node matched", type, memberAttribute.Property)); } member.SetValue(obj, ConvertGraphToTypedObject(memberObjectGraph, member.PropertyType)); } } } return(obj); }
/// <summary> /// Create a graph of typed objects using the type graph as a model /// </summary> private LabelledTreeNode <object, Term> TypifyGraph(LabelledTreeNode <object, Term> objectGraph, LabelledTreeNode <Type, Term> typeGraph) { var obj = ConvertGraphToTypedObject(objectGraph, typeGraph.Value); var typedGraph = new LabelledTreeNode <object, Term>(obj); foreach (var outEdge in typeGraph.Children) { var edge = outEdge.Edge; var childTypeGraph = outEdge.TerminalNode; var childObjectGraphs = objectGraph.Descend(edge); foreach (var childObjectGraph in childObjectGraphs) { typedGraph.AddChild(edge, TypifyGraph(childObjectGraph, childTypeGraph)); } } return(typedGraph); }
/// <summary> /// Generate a bgp regex filter using the variable names in the object graph /// </summary> /// <param name="queryGraph">graph model of the query</param> /// <returns></returns> public IFilter Generate(LabelledTreeNode <object, Term> queryGraph) { var propertyInfo = typeof(T).GetPropertyInfo(_propertyLambda); if (propertyInfo.Name == "Id") { var variable = queryGraph.Value as Variable; return(variable != null ? new RegexFilter($"str({variable})", _regex) : null); } var attribute = propertyInfo.CustomAttributes.OfType <PropertyBindAttribute>().SingleOrDefault(); if (attribute != null) { var node = queryGraph.Descend(attribute.Property).Single(); var variable = node.Value as Variable; return(variable != null ? new RegexFilter(variable.ToString(), _regex) : null); } return(null); }