/// <summary> /// Initializes a new instance of the <see cref="MappingKey"/> class. /// </summary> /// <param name="key">The key.</param> /// <param name="path">The path.</param> /// <param name="schema">The schema.</param> public MappingKey(string key, AttributePath path, ValueSchema schema) : this(key) { if (path != null) { this.Path = path; } this.Schema = schema; if (this.Schema.IsBlock) { this.InitialAnalysis = this.Schema.IsListOrSet ? AttributeContent.BlockList : AttributeContent.BlockObject; } else if (this.Schema.IsListOrSet) { this.InitialAnalysis = AttributeContent.Sequence; } else if (this.Schema.IsScalar) { this.InitialAnalysis = AttributeContent.Value; } else if (this.Schema.Type == SchemaValueType.TypeMap) { this.InitialAnalysis = AttributeContent.Mapping; } else { this.InitialAnalysis = AttributeContent.None; } }
public void ShouldSplitIndexedPath() { const string Path = "key1['multi.part.key']"; var expected = new[] { "key1", "multi.part.key" }; AttributePath.Split(Path).Should().BeEquivalentTo(expected); }
/// <summary> /// This method will make an AttributePath for a given an EFObject. /// </summary> private static AttributePath MakeAttributePathFromEFObject(EFObject efobject) { var attributePath = new AttributePath(); var curr = efobject.XObject; while (curr != null) { if (curr.NodeType == XmlNodeType.Document) { var doc = (XDocument)curr; attributePath.PushFront(doc.Root.Name.LocalName, doc.Root.Name.Namespace.NamespaceName, true); } else if (curr.NodeType == XmlNodeType.Attribute) { var attr = (XAttribute)curr; attributePath.PushFront(attr.Name.LocalName, attr.Name.Namespace.NamespaceName, false); } else if (curr.NodeType == XmlNodeType.Element) { var el = (XElement)curr; attributePath.PushFront(el.Name.LocalName, el.Name.Namespace.NamespaceName, true); } else { Debug.Fail("Unexpected XObject type is neither an attribute nor an element"); return(null); } curr = curr.Parent; } return(attributePath); }
internal AttributePath Clone() { var clone = new AttributePath(); var array = _stack.ToArray(); for (var i = array.Length - 1; i > -1; i--) { clone._stack.Push(array[i]); } return(clone); }
/// <summary> /// Validates a proposed string against a given "path" to a node. /// </summary> /// <param name="proposedString"></param> /// <param name="attributePath"></param> /// <returns></returns> internal bool IsValidStringForSchemaType(string proposedString, AttributePath attributePath) { var type = GetTypeNameForNode(attributePath); if (type == null) { Debug.Fail("didn't find XmlSchemaType for given attribute path"); return false; } else { return IsValidStringForSchemaType(proposedString, type.QualifiedName); } }
/// <summary> /// Validates a proposed string against a given "path" to a node. /// </summary> /// <param name="proposedString"></param> /// <param name="attributePath"></param> /// <returns></returns> internal bool IsValidStringForSchemaType(string proposedString, AttributePath attributePath) { var type = GetTypeNameForNode(attributePath); if (type == null) { Debug.Fail("didn't find XmlSchemaType for given attribute path"); return(false); } else { return(IsValidStringForSchemaType(proposedString, type.QualifiedName)); } }
private static LinqExpression GetPathExpression(AttributePath path, LinqExpression representationAttrExpr) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (representationAttrExpr == null) { throw new ArgumentNullException(nameof(representationAttrExpr)); } var schemaAttributeParameter = LinqExpression.Property(representationAttrExpr, "SchemaAttribute"); var propertyName = LinqExpression.Property(schemaAttributeParameter, "Name"); var notNull = LinqExpression.NotEqual(schemaAttributeParameter, LinqExpression.Constant(null)); var equal = LinqExpression.Equal(propertyName, LinqExpression.Constant(path.Name)); return(LinqExpression.AndAlso(notNull, equal)); }
/// <summary> /// This is a convenience method that will create an AttributePath instance from a string of the form "xxx/yyy/zzz/attr". This assumes that /// "attr" is the name of an attribute with no namespace value, and that "xxx", "yyy" and "zzz" are element names with namespace nameSpaceUri. /// This is a valid assumption for CSDL, SSDL & MSL XSD definitions, but is not necessarily true for all XSDs. /// </summary> internal static AttributePath MakeAttributePathFromString(string nameSpaceUri, string path) { var parts = path.Split('/'); var attributePath = new AttributePath(); for (var i = parts.Length - 1; i >= 0; --i) { // assume that the last one is always an attribute with empty namespace URI. This is a valid assumption for our csdl/ssdl/msl cases if (i == parts.Length - 1) { attributePath.PushFront(parts[i], String.Empty, false); } else { attributePath.PushFront(parts[i], nameSpaceUri, true); } } return(attributePath); }
private static LinqExpression EvaluateSelection(this AttributePath path, LinqExpression outerExpression) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (outerExpression == null) { throw new ArgumentNullException(nameof(outerExpression)); } var resourceAttrParameterExpr = LinqExpression.Parameter(typeof(RepresentationAttribute), "a"); var equality = GetPathExpression(path, resourceAttrParameterExpr); var call = LinqExpression.Lambda <Func <RepresentationAttribute, bool> >(equality, resourceAttrParameterExpr); var whereMethod = GetWhereMethod <RepresentationAttribute>(); var result = LinqExpression.Call(whereMethod, outerExpression, call); var enumerableType = typeof(Queryable); var enumerableMethods = enumerableType.GetMethods(); if (path.Next != null) { var next = path.Next; var outerArg = LinqExpression.Parameter(typeof(RepresentationAttribute), "x"); var innerArg = LinqExpression.Parameter(typeof(RepresentationAttribute), "y"); var outerProperty = LinqExpression.Property(outerArg, "Id"); var innerProperty = LinqExpression.Property(innerArg, "RepresentationAttributeIdParent"); var outerLambda = LinqExpression.Lambda(outerProperty, new System.Linq.Expressions.ParameterExpression[] { outerArg }); var innerLambda = LinqExpression.Lambda(innerProperty, new System.Linq.Expressions.ParameterExpression[] { innerArg }); var resultSelector = LinqExpression.Lambda(innerArg, new System.Linq.Expressions.ParameterExpression[] { outerArg, innerArg }); var joinMethod = enumerableMethods.Where(m => m.Name == "Join" && m.IsGenericMethodDefinition).Where(m => m.GetParameters().ToList().Count == 5).First(); var joinGenericMethod = joinMethod.MakeGenericMethod(typeof(RepresentationAttribute), typeof(RepresentationAttribute), typeof(string), typeof(RepresentationAttribute)); result = LinqExpression.Call(joinGenericMethod, result, outerExpression, outerLambda, innerLambda, resultSelector); // add join. return(EvaluateSelection(next, result)); } return(result); }
private static LinqExpression Evaluate(this AttributePath attributePath, System.Linq.Expressions.ParameterExpression resourceAttrParameterExpr) { if (attributePath == null) { throw new ArgumentNullException(nameof(attributePath)); } var result = GetPathExpression(attributePath, resourceAttrParameterExpr); if (attributePath.ValueFilter != null) { var anyExpr = BuildChildrenExpr(attributePath.ValueFilter.Expression, resourceAttrParameterExpr); result = LinqExpression.AndAlso(result, anyExpr); } if (attributePath.Next != null) { var anyExpr = EvaluateChildren(attributePath, resourceAttrParameterExpr, null); result = LinqExpression.AndAlso(result, anyExpr); } return(result); }
/// <summary> /// Returns the XmlSchemaType for the given node. /// </summary> /// <param name="attributePath"></param> /// <returns></returns> protected XmlSchemaType GetTypeNameForNode(AttributePath attributePath) { if (attributePath == null) { throw new ArgumentNullException("attributePath"); } var attributePathCopy = attributePath.Clone(); if (attributePathCopy.Count < 1) { return null; } // prime the pump. The first node on the stack should be a global element. var curr = attributePathCopy.PopFront(); var schemaElement = GetXmlSchemaObject(SchemaSet.GlobalElements, curr.qname) as XmlSchemaElement; if (schemaElement == null) { Debug.Fail("Unable to find Global Schema Element " + curr.qname); return null; } var schemaType = GetXmlSchemaTypeFromXmlSchemaElement(schemaElement); if (schemaType == null) { Debug.Fail("Unable to find schema type for schema element " + curr.qname); return null; } while (attributePathCopy.Count > 0) { curr = attributePathCopy.PopFront(); var xsct = schemaType as XmlSchemaComplexType; if (xsct != null) { if (curr.type == AttributePath.QNameNodeTypePair.NodeType.Element) { XmlSchemaElement xe = null; while (xe == null && xsct != null) { xe = GetXmlSchemaElementFromParticle(xsct.Particle, curr.qname); if (xe == null) { // check the content type particle xe = GetXmlSchemaElementFromParticle(xsct.ContentTypeParticle, curr.qname); } if (xe == null) { // check the base type xsct = xsct.BaseXmlSchemaType as XmlSchemaComplexType; } } if (xe == null) { Debug.Fail("didn't find XmlSchemaElement for qname " + curr.qname + " in type " + schemaType.QualifiedName); return null; } else { schemaType = GetXmlSchemaTypeFromXmlSchemaElement(xe); } } else { // we need to find an attribute // see if it is a global attribute first var xa = GetXmlSchemaObject(SchemaSet.GlobalAttributes, curr.qname) as XmlSchemaAttribute; // if that doesn't work try to see whether it's an attribute on the XmlSchemaComplexType xsct if (xa == null) { xa = GetXmlSchemaAttributeFromXmlSchemaGroupBase(xsct, curr.qname); } if (xa == null) { Debug.Fail( "didn't find XmlSchemaAttribute for qname " + curr.qname + " in Global Attributes or in type " + xsct.QualifiedName); return null; } else { schemaType = GetXmlSchemaTypeFromXmlSchemaAttribute(xa); } } } else { Debug.Fail("not yet implemented!"); } } return schemaType; }
private static LinqExpression EvaluateChildren(AttributePath path, System.Linq.Expressions.ParameterExpression arg, Func <System.Linq.Expressions.ParameterExpression, LinqExpression> callback = null) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (arg == null) { throw new ArgumentNullException(nameof(arg)); } var subArg = LinqExpression.Parameter(typeof(RepresentationAttribute), GetSc()); var subChild = LinqExpression.Parameter(typeof(RepresentationAttribute), GetSc()); var childrenProperty = LinqExpression.Property(arg, "Children"); var argChildrenProperty = LinqExpression.Property(subArg, "Children"); var schemaAttributeProperty = LinqExpression.Property(arg, "SchemaAttribute"); var schemaTypeProperty = LinqExpression.Property(schemaAttributeProperty, "Type"); var schemaMultiValuedProperty = LinqExpression.Property(schemaAttributeProperty, "MultiValued"); var isMultiValued = LinqExpression.Equal(schemaMultiValuedProperty, LinqExpression.Constant(true)); // true var isNotMultiValued = LinqExpression.Equal(schemaMultiValuedProperty, LinqExpression.Constant(false)); var isTypeComplex = LinqExpression.Equal(schemaTypeProperty, LinqExpression.Constant(Common.Constants.SchemaAttributeTypes.Complex)); var isNotTypeComplex = LinqExpression.NotEqual(schemaTypeProperty, LinqExpression.Constant(Common.Constants.SchemaAttributeTypes.Complex)); var isComplexMultiValued = LinqExpression.AndAlso(isMultiValued, isTypeComplex); var isNotComplexMultiValued = LinqExpression.OrElse(isNotTypeComplex, isNotMultiValued); var itemCount = LinqExpression.Call(typeof(Enumerable), "Count", new[] { typeof(RepresentationAttribute) }, childrenProperty); var moreThanZero = LinqExpression.GreaterThan(itemCount, LinqExpression.Constant(0)); LinqExpression result = null; if (callback != null) { result = callback(subChild); } if (path.Next != null) { var subCond = path.Next.Evaluate(subChild); if (result != null) { result = LinqExpression.AndAlso(result, subCond); } else { result = subCond; } } // a => aaze = azeaze var callEqualValue = LinqExpression.Lambda <Func <RepresentationAttribute, bool> >(result, subChild); // c => c.value = <value> var anyComplexMultiValuedSubAnyExpr = LinqExpression.Call(typeof(Enumerable), _anyMethodName, new[] { typeof(RepresentationAttribute) }, argChildrenProperty, callEqualValue); var lambdaMultiValuedSubAnyExpr = LinqExpression.Lambda <Func <RepresentationAttribute, bool> >(anyComplexMultiValuedSubAnyExpr, subArg); var anyComplexMultiValuedAnyExpr = LinqExpression.Call(typeof(Enumerable), _anyMethodName, new[] { typeof(RepresentationAttribute) }, childrenProperty, lambdaMultiValuedSubAnyExpr); var anyNotComplexMultiValuedExpr = LinqExpression.Call(typeof(Enumerable), _anyMethodName, new[] { typeof(RepresentationAttribute) }, childrenProperty, callEqualValue); var firstNotComplexMultiValued = LinqExpression.AndAlso(isNotComplexMultiValued, moreThanZero); var notComplexMultiValued = LinqExpression.AndAlso(firstNotComplexMultiValued, anyNotComplexMultiValuedExpr); var firstComplexMultiValued = LinqExpression.AndAlso(isComplexMultiValued, moreThanZero); var complexMultiValued = LinqExpression.AndAlso(firstComplexMultiValued, anyComplexMultiValuedAnyExpr); return(LinqExpression.OrElse(complexMultiValued, notComplexMultiValued)); }
internal AttributePath Clone() { var clone = new AttributePath(); var array = _stack.ToArray(); for (var i = array.Length - 1; i > -1; i--) { clone._stack.Push(array[i]); } return clone; }
/// <summary> /// This method will make an AttributePath for a given an EFObject. /// </summary> private static AttributePath MakeAttributePathFromEFObject(EFObject efobject) { var attributePath = new AttributePath(); var curr = efobject.XObject; while (curr != null) { if (curr.NodeType == XmlNodeType.Document) { var doc = (XDocument)curr; attributePath.PushFront(doc.Root.Name.LocalName, doc.Root.Name.Namespace.NamespaceName, true); } else if (curr.NodeType == XmlNodeType.Attribute) { var attr = (XAttribute)curr; attributePath.PushFront(attr.Name.LocalName, attr.Name.Namespace.NamespaceName, false); } else if (curr.NodeType == XmlNodeType.Element) { var el = (XElement)curr; attributePath.PushFront(el.Name.LocalName, el.Name.Namespace.NamespaceName, true); } else { Debug.Fail("Unexpected XObject type is neither an attribute nor an element"); return null; } curr = curr.Parent; } return attributePath; }
/// <summary> /// Returns the XmlSchemaType for the given node. /// </summary> /// <param name="attributePath"></param> /// <returns></returns> protected XmlSchemaType GetTypeNameForNode(AttributePath attributePath) { if (attributePath == null) { throw new ArgumentNullException("attributePath"); } var attributePathCopy = attributePath.Clone(); if (attributePathCopy.Count < 1) { return(null); } // prime the pump. The first node on the stack should be a global element. var curr = attributePathCopy.PopFront(); var schemaElement = GetXmlSchemaObject(SchemaSet.GlobalElements, curr.qname) as XmlSchemaElement; if (schemaElement == null) { Debug.Fail("Unable to find Global Schema Element " + curr.qname); return(null); } var schemaType = GetXmlSchemaTypeFromXmlSchemaElement(schemaElement); if (schemaType == null) { Debug.Fail("Unable to find schema type for schema element " + curr.qname); return(null); } while (attributePathCopy.Count > 0) { curr = attributePathCopy.PopFront(); var xsct = schemaType as XmlSchemaComplexType; if (xsct != null) { if (curr.type == AttributePath.QNameNodeTypePair.NodeType.Element) { XmlSchemaElement xe = null; while (xe == null && xsct != null) { xe = GetXmlSchemaElementFromParticle(xsct.Particle, curr.qname); if (xe == null) { // check the content type particle xe = GetXmlSchemaElementFromParticle(xsct.ContentTypeParticle, curr.qname); } if (xe == null) { // check the base type xsct = xsct.BaseXmlSchemaType as XmlSchemaComplexType; } } if (xe == null) { Debug.Fail("didn't find XmlSchemaElement for qname " + curr.qname + " in type " + schemaType.QualifiedName); return(null); } else { schemaType = GetXmlSchemaTypeFromXmlSchemaElement(xe); } } else { // we need to find an attribute // see if it is a global attribute first var xa = GetXmlSchemaObject(SchemaSet.GlobalAttributes, curr.qname) as XmlSchemaAttribute; // if that doesn't work try to see whether it's an attribute on the XmlSchemaComplexType xsct if (xa == null) { xa = GetXmlSchemaAttributeFromXmlSchemaGroupBase(xsct, curr.qname); } if (xa == null) { Debug.Fail( "didn't find XmlSchemaAttribute for qname " + curr.qname + " in Global Attributes or in type " + xsct.QualifiedName); return(null); } else { schemaType = GetXmlSchemaTypeFromXmlSchemaAttribute(xa); } } } else { Debug.Fail("not yet implemented!"); } } return(schemaType); }
/// <summary> /// This is a convenience method that will create an AttributePath instance from a string of the form "xxx/yyy/zzz/attr". This assumes that /// "attr" is the name of an attribute with no namespace value, and that "xxx", "yyy" and "zzz" are element names with namespace nameSpaceUri. /// This is a valid assumption for CSDL, SSDL & MSL XSD definitions, but is not necessarily true for all XSDs. /// </summary> internal static AttributePath MakeAttributePathFromString(string nameSpaceUri, string path) { var parts = path.Split('/'); var attributePath = new AttributePath(); for (var i = parts.Length - 1; i >= 0; --i) { // assume that the last one is always an attribute with empty namespace URI. This is a valid assumption for our csdl/ssdl/msl cases if (i == parts.Length - 1) { attributePath.PushFront(parts[i], String.Empty, false); } else { attributePath.PushFront(parts[i], nameSpaceUri, true); } } return attributePath; }
/// <summary> /// Gets an attribute schema given path to it. /// </summary> /// <param name="path">The path.</param> /// <param name="resourceTraits">Locally maintained traits that can influence the returned schema.</param> /// <returns>A <see cref="ValueSchema"/> for the attribute.</returns> /// <exception cref="System.ArgumentException"> /// Value must be provided - path /// or /// Invalid attribute path \"{path}\" - path /// </exception> /// <exception cref="System.InvalidOperationException"> /// Invalid path \"{path}\": Attribute at \"{GetCurrentPathFromPathStack(processedPath)}\" is not a set or a list. /// or /// Invalid path \"{path}\": Attribute at \"{GetCurrentPathFromPathStack(processedPath)}\" is not a set or a list. /// </exception> /// <exception cref="System.Collections.Generic.KeyNotFoundException"> /// Resource does not contain an attribute \"{currentAttributeName}\". /// or /// Resource does not contain an attribute at\"{path}\". /// </exception> public ValueSchema GetAttributeByPath(string path, IResourceTraits resourceTraits) { if (string.IsNullOrEmpty(path)) { throw new ArgumentException("Value must be provided", nameof(path)); } if (IsListIndexIndicator(path.First().ToString()) || IsListIndexIndicator(path.Last().ToString(), true)) { throw new ArgumentException($"Invalid attribute path \"{path}\"", nameof(path)); } if (path == "id") { // 'id' is not stored in the schema because _everything_ has it return(IdentitySchema); } if (resourceTraits.MissingFromSchema.Contains(path)) { return(MissingFromSchemaValueSchema); } ValueSchema currentAttribute = null; var currentResource = this; var pathComponents = new Queue <string>(AttributePath.Split(path)); var processedPath = new Stack <string>(); while (true) { var currentAttributeName = pathComponents.Dequeue(); if (IsListIndexIndicator(currentAttributeName)) { processedPath.Push(currentAttributeName); continue; } var previousAttribute = currentAttribute; if (previousAttribute != null && previousAttribute.Type != SchemaValueType.TypeObject) { // To get here, the previous attribute must be a set or list if (!IsListIndexIndicator(processedPath.FirstOrDefault())) { throw new InvalidOperationException( $"Invalid path \"{path}\": Attribute at \"{GetCurrentPathFromPathStack()}\" is a set or a list. List indicator ('*', '#' or integer) was expected next in path."); } } if (currentAttributeName == "timeouts") { currentAttribute = TimeoutsSchema; } else { if (!currentResource.Attributes.ContainsKey(currentAttributeName)) { throw CreateKeyNotFoundException(); } currentAttribute = currentResource.Attributes[currentAttributeName]; } processedPath.Push(currentAttributeName); if (pathComponents.Count == 0) { return(currentAttribute); } switch (currentAttribute.Elem) { case ProviderResourceSchema resourceSchema: currentResource = resourceSchema; break; case ValueSchema valueSchema when pathComponents.Count == 1 && currentAttribute.Type == SchemaValueType.TypeMap: return(valueSchema); default: // If Elem is null or contains a value schema, then there are no further path components // below this attribute. throw CreateKeyNotFoundException(); } } KeyNotFoundException CreateKeyNotFoundException() { return(new KeyNotFoundException($"Resource does not contain an attribute at\"{path}\".")); } string GetCurrentPathFromPathStack() { return(string.Join(".", processedPath.Reverse().ToList())); } }
public void ShouldSplitNormalPath() { const string Path = "key1.0.key2"; AttributePath.Split(Path).Should().BeEquivalentTo(Path.Split('.')); }