private bool StructuralTypesAreEqual(QueryStructuralType firstStructuralType, QueryStructuralType secondStructuralType) { var firstComplexType = firstStructuralType as QueryComplexType; if (firstComplexType != null) { var secondComplexType = secondStructuralType as QueryComplexType; return(secondComplexType != null && firstComplexType.ComplexType.Equals(secondComplexType.ComplexType)); } var firstEntityType = firstStructuralType as QueryEntityType; if (firstEntityType != null) { var secondEntityType = secondStructuralType as QueryEntityType; return(secondEntityType != null && firstEntityType.EntityType.Equals(secondEntityType.EntityType)); } var firstAnonymousType = firstStructuralType as QueryAnonymousStructuralType; if (firstAnonymousType != null) { var secondAnonymousType = secondStructuralType as QueryAnonymousStructuralType; return(secondAnonymousType != null && firstAnonymousType.Equals(secondAnonymousType)); } var firstGroupingType = firstStructuralType as QueryGroupingType; ExceptionUtilities.Assert(firstGroupingType != null, "Unknown QueryStructuralType: {0}", firstStructuralType); var secondGroupingType = secondStructuralType as QueryGroupingType; return(secondGroupingType != null); }
/// <summary> /// Initializes a new instance of the QueryStructuralValue class. /// </summary> /// <param name="type">The type of the value.</param> /// <param name="isNull">If set to <c>true</c> the structural value is null.</param> /// <param name="evaluationError">The evaluation error.</param> /// <param name="evaluationStrategy">The evaluation strategy.</param> public QueryStructuralValue(QueryStructuralType type, bool isNull, QueryError evaluationError, IQueryEvaluationStrategy evaluationStrategy) : base(evaluationError, evaluationStrategy) { ExceptionUtilities.CheckArgumentNotNull(type, "type"); this.Type = type; this.isNull = isNull; }
private QueryValue TreatAs(QueryStructuralType structuralType) { if (structuralType.IsAssignableFrom(this.Type)) { return(this); } return(structuralType.NullValue); }
/// <summary> /// Converts the <see cref="QueryValue"/> to a particular <see cref="QueryType"/>. /// </summary> /// <param name="type">The type for the As operation.</param> /// <returns>The <see cref="QueryValue"/> converted to the specified type if successful. Returns null if this operation fails.</returns> public override QueryValue TreatAs(QueryType type) { QueryStructuralType structuralType = type as QueryStructuralType; if (structuralType == null) { return(this.Type.CreateErrorValue(new QueryError("Invalid 'As' Operation : Cannot perform an 'As' of a structural type to a non-structural type"))); } return(this.TreatAs(structuralType)); }
/// <summary> /// Gets all the nested properties of a structural type recursively. /// </summary> /// <param name="structuralType">The type from which to extra properties.</param> /// <param name="operationFilter">The filter to apply based on supported operations of each property.</param> /// <param name="navigationPropertyFilter">The filter to apply based on whether or not to select navigation properties.</param> /// <returns>A list of string arrays representing the property paths to each property (including nested properties) in the entity.</returns> protected IEnumerable <string[]> GetAllNestedPropertyPaths(QueryStructuralType structuralType, SupportOperationsFilter operationFilter, NavigationPropertyFilter navigationPropertyFilter) { IList <string[]> allPropertyPaths = new List <string[]>(); foreach (var property in structuralType.Properties) { var propertyType = property.PropertyType; var qst = propertyType as QueryScalarType; var qcxt = propertyType as QueryComplexType; var qct = propertyType as QueryCollectionType; if (qst != null) { if (operationFilter == SupportOperationsFilter.NoFilter || (operationFilter == SupportOperationsFilter.ArithmeticOperable && this.SupportsArithmeticOperations(qst)) || (operationFilter == SupportOperationsFilter.EqualComparable && qst.SupportsEqualityComparison) || (operationFilter == SupportOperationsFilter.OrderComparable && qst.SupportsOrderComparison)) { if (navigationPropertyFilter != NavigationPropertyFilter.NavigationOnly) { allPropertyPaths.Add(new string[] { property.Name }); } } } else if (qcxt != null) { // For complex types recursively find child properties and add them to the list of property paths. var nestedTypePaths = this.GetAllNestedPropertyPaths(qcxt, operationFilter, navigationPropertyFilter); foreach (var nestedTypePath in nestedTypePaths) { var propertyPath = new string[] { property.Name }; propertyPath = propertyPath.Concat(nestedTypePath).ToArray(); if (navigationPropertyFilter != NavigationPropertyFilter.NavigationOnly) { allPropertyPaths.Add(propertyPath); } } } else if (qct != null) { if (navigationPropertyFilter != NavigationPropertyFilter.NonNavigationOnly) { allPropertyPaths.Add(new string[] { property.Name }); } } } return(allPropertyPaths.AsEnumerable()); }
/// <summary> /// Returns an enumeration of the type's ancestor types and itself /// </summary> /// <param name="type">The type to get base types of</param> /// <returns>An enumeration containing the base types and the given type</returns> public static IEnumerable <QueryStructuralType> GetBaseTypesAndSelf(this QueryStructuralType type) { ExceptionUtilities.CheckArgumentNotNull(type, "type"); var list = new List <QueryStructuralType> { type }; while (type.Parent != null) { list.Insert(0, type.Parent); type = type.Parent; } return(list.AsEnumerable()); }
/// <summary> /// Casts a <see cref="QueryValue"/> to a <see cref="QueryType"/>. The cast will return the value type cast to the new type. /// </summary> /// <param name="type">The type for the cast operation.</param> /// <returns><see cref="QueryValue"/> which is cast to the appropriate type</returns> public override QueryValue Cast(QueryType type) { QueryStructuralType structuralType = type as QueryStructuralType; if (structuralType == null) { return(this.Type.CreateErrorValue(new QueryError("Invalid Cast : Cannot perform a cast of a structural type to a non-structural type"))); } QueryValue result = this.TreatAs(structuralType); if (result.IsNull) { return(this.Type.CreateErrorValue(new QueryError("Invalid Cast : Cannot perform Cast to the specified type"))); } return(result); }
/// <summary> /// Determines if the current value is of a given type or an equivalent type in the type hierarchy /// </summary> /// <param name="resultType">The type to compare against</param> /// <param name="performExactMatch">A flag that determines if an exact match needs to be performed</param> /// <returns>The elements from the collection, that match the input type or an equivalent type</returns> public QueryValue OfType(QueryStructuralType resultType, bool performExactMatch) { QueryCollectionValue result = resultType.CreateCollectionType().CreateCollectionWithValues(Enumerable.Empty <QueryValue>()); if (!this.IsNull) { foreach (QueryStructuralValue element in this.Elements) { bool isOfEquivalentType = (bool)((QueryScalarValue)element.IsOf(resultType, performExactMatch)).Value; if (isOfEquivalentType) { result.Elements.Add(element.TreatAs(resultType)); } } } return(result); }
/// <summary> /// Creates a strongly-typed QueryProperty of T /// </summary> /// <param name="propertyName">The name of the property.</param> /// <param name="propertyType">Type of the property.</param> /// <returns>Strongly typed QueryProperty of T.</returns> public static QueryProperty <QueryStructuralType> Create(string propertyName, QueryStructuralType propertyType) { ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); ExceptionUtilities.CheckArgumentNotNull(propertyType, "propertyType"); return(new QueryProperty <QueryStructuralType>(propertyName, propertyType)); }
private IEnumerable <QueryScalarValue> GetPropertyRows(IEnumerable <QueryStructuralValue> dataRows, IList <string> propertyPaths, QueryStructuralType rowType) { var currentPropertyPath = propertyPaths[0]; var nestedPropertyType = rowType.Properties.Where(p => p.Name == currentPropertyPath).Single().PropertyType; if (propertyPaths.Count == 1) { var nestedScalarType = nestedPropertyType as QueryScalarType; ExceptionUtilities.CheckObjectNotNull(nestedScalarType, "The leaf property of any structural type must be a scalar type"); var propertyDataSet = dataRows.Select(qsv => qsv.GetValue(currentPropertyPath)); if (propertyDataSet.Count() > 0) { ExceptionUtilities.Assert(propertyDataSet.First() is QueryScalarValue, "Type mismatch between property type and data set, property {0} should be a scalar value in the dataSet", currentPropertyPath); return(propertyDataSet.Cast <QueryScalarValue>()); } else { var propertyDataSetList = new List <QueryScalarValue>(); propertyDataSetList.Add(nestedScalarType.DefaultValue as QueryScalarValue); return(propertyDataSetList.AsEnumerable <QueryScalarValue>()); } } else { // if we are not at the leaf property, find it recursively. var nestedStructuralType = nestedPropertyType as QueryStructuralType; ExceptionUtilities.CheckObjectNotNull(nestedStructuralType, "A non-leaf property of a structural type must be a structural type"); propertyPaths.RemoveAt(0); var nestedProperties = dataRows.Select(qsv => qsv.GetValue(currentPropertyPath)).Cast <QueryStructuralValue>(); return(this.GetPropertyRows(nestedProperties, propertyPaths, nestedStructuralType)); } }
/// <summary> /// Creates a QueryProperty for a property that is a non entity Collection /// </summary> /// <param name="library">Library Query Type</param> /// <param name="result">resulting Query Structural Type</param> /// <param name="collectionProperty">Member to calculate</param> /// <param name="pathToProperty">Path to the Property</param> /// <returns>A Query Property of the collectionType</returns> protected virtual QueryProperty CreateNonentityCollectionMember(QueryTypeLibrary library, QueryStructuralType result, MemberProperty collectionProperty, PathToProperty pathToProperty) { throw new TaupoNotSupportedException("This type of property is not supported."); }
/// <summary> /// Creates new members on a structural type /// </summary> /// <param name="library">Type library</param> /// <param name="result">Structural Type to add members to</param> /// <param name="properties">Properties of the Structural Type member</param> /// <param name="pathToProperty">Path to the Property</param> protected void CreateMembers(QueryTypeLibrary library, QueryStructuralType result, IEnumerable<MemberProperty> properties, PathToProperty pathToProperty) { // TODO: Some Taupo framework pieces skip over StreamDataType properties foreach (var prop in properties.Where(p => !(p.PropertyType is StreamDataType))) { QueryProperty queryProperty = null; pathToProperty.PathStackWithinEntityType.Add(prop.Name); var pdt = prop.PropertyType as PrimitiveDataType; var cdt = prop.PropertyType as ComplexDataType; if (pdt != null) { QueryScalarType queryPropertyType = this.GetQueryTypeForMappedProperty(pathToProperty, library, pdt); queryProperty = QueryProperty.Create(prop.Name, queryPropertyType); } else if (cdt != null) { ComplexType ct = cdt.Definition; QueryComplexType queryComplexType = this.CreateStubComplexType(ct); this.CreateMembers(library, queryComplexType, ct.Properties, pathToProperty); library.SetQueryComplexType(ct, queryComplexType); queryProperty = QueryProperty.Create(prop.Name, queryComplexType); } else { queryProperty = this.CreateNonentityCollectionMember(library, result, prop, pathToProperty); } pathToProperty.PathStackWithinEntityType.RemoveAt(pathToProperty.PathStackWithinEntityType.Count - 1); queryProperty.SetPrimaryKey(prop.IsPrimaryKey); result.Add(queryProperty); } }
/// <summary> /// Creates a QueryProperty for a property that is a non entity Collection /// </summary> /// <param name="library">Library Query Type</param> /// <param name="result">resulting Query Structural Type</param> /// <param name="collectionProperty">Member to calculate</param> /// <param name="pathToProperty">Path to the Property</param> /// <returns>A Query Property of the collectionType</returns> protected override QueryProperty CreateNonentityCollectionMember(QueryTypeLibrary library, QueryStructuralType result, MemberProperty collectionProperty, PathToProperty pathToProperty) { ExceptionUtilities.CheckArgumentNotNull(collectionProperty, "collectionProperty"); var collectionType = collectionProperty.PropertyType as CollectionDataType; ExceptionUtilities.Assert(collectionType != null, "This type of property is not supported."); var collectionPrimitiveElementType = collectionType.ElementDataType as PrimitiveDataType; var collectionComplexElementType = collectionType.ElementDataType as ComplexDataType; QueryCollectionType queryCollectionType = null; if (collectionPrimitiveElementType != null) { QueryScalarType queryPropertyType = this.GetQueryTypeForMappedProperty(pathToProperty, library, collectionPrimitiveElementType); queryCollectionType = queryPropertyType.CreateCollectionType(); } else { ExceptionUtilities.Assert(collectionComplexElementType != null, "This type of property is not supported."); QueryComplexType queryComplexType = this.CreateStubComplexType(collectionComplexElementType.Definition); CreateMembers(library, queryComplexType, collectionComplexElementType.Definition.Properties, pathToProperty); queryCollectionType = queryComplexType.CreateCollectionType(); } return QueryProperty.Create(collectionProperty.Name, queryCollectionType); }
/// <summary> /// Get properties in the structural type that support a specific Binary Operation. /// </summary> /// <param name="type">Structural Type.</param> /// <param name="op">An enum that represents a Query Binary Operation.</param> /// <returns>A collection of properties.</returns> protected IEnumerable<QueryProperty<QueryScalarType>> GetPropertiesWithBinaryOpSupport(QueryStructuralType type, QueryBinaryOperation op) { List<QueryProperty<QueryScalarType>> queryProperties = type.Properties.Primitive().Where(m => m.PropertyType.Supports(op)).ToList(); DataServiceExecuteVerifier verifier = this.Verifier as DataServiceExecuteVerifier; if (verifier != null && verifier.IsUri == false) { if (op == QueryBinaryOperation.GreaterThan || op == QueryBinaryOperation.GreaterThanOrEqualTo || op == QueryBinaryOperation.LessThan || op == QueryBinaryOperation.LessThanOrEqualTo) { // Exclude string, DateTime and boolean properties as these don't support greater than or less than operators in the Client Linq Code queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(string)).ToList(); queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(bool)).ToList(); queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(DateTime)).ToList(); #if !WINDOWS_PHONE queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(Guid)).ToList(); #endif } } return queryProperties; }
private MaskedQueryStructuralValue(QueryStructuralType type, bool isNull, QueryError evaluationError, IQueryEvaluationStrategy evaluationStrategy) : base(type, isNull, evaluationError, evaluationStrategy) { }
/// <summary> /// Gets all the nested properties of a structural type recursively. /// </summary> /// <param name="structuralType">The type from which to extra properties.</param> /// <param name="operationFilter">The filter to apply based on supported operations of each property.</param> /// <param name="navigationPropertyFilter">The filter to apply based on whether or not to select navigation properties.</param> /// <returns>A list of string arrays representing the property paths to each property (including nested properties) in the entity.</returns> protected IEnumerable<string[]> GetAllNestedPropertyPaths(QueryStructuralType structuralType, SupportOperationsFilter operationFilter, NavigationPropertyFilter navigationPropertyFilter) { IList<string[]> allPropertyPaths = new List<string[]>(); foreach (var property in structuralType.Properties) { var propertyType = property.PropertyType; var qst = propertyType as QueryScalarType; var qcxt = propertyType as QueryComplexType; var qct = propertyType as QueryCollectionType; if (qst != null) { if (operationFilter == SupportOperationsFilter.NoFilter || (operationFilter == SupportOperationsFilter.ArithmeticOperable && this.SupportsArithmeticOperations(qst)) || (operationFilter == SupportOperationsFilter.EqualComparable && qst.SupportsEqualityComparison) || (operationFilter == SupportOperationsFilter.OrderComparable && qst.SupportsOrderComparison)) { if (navigationPropertyFilter != NavigationPropertyFilter.NavigationOnly) { allPropertyPaths.Add(new string[] { property.Name }); } } } else if (qcxt != null) { // For complex types recursively find child properties and add them to the list of property paths. var nestedTypePaths = this.GetAllNestedPropertyPaths(qcxt, operationFilter, navigationPropertyFilter); foreach (var nestedTypePath in nestedTypePaths) { var propertyPath = new string[] { property.Name }; propertyPath = propertyPath.Concat(nestedTypePath).ToArray(); if (navigationPropertyFilter != NavigationPropertyFilter.NavigationOnly) { allPropertyPaths.Add(propertyPath); } } } else if (qct != null) { if (navigationPropertyFilter != NavigationPropertyFilter.NonNavigationOnly) { allPropertyPaths.Add(new string[] { property.Name }); } } } return allPropertyPaths.AsEnumerable(); }
private IEnumerable<QueryScalarValue> GetPropertyRows(IEnumerable<QueryStructuralValue> dataRows, IList<string> propertyPaths, QueryStructuralType rowType) { var currentPropertyPath = propertyPaths[0]; var nestedPropertyType = rowType.Properties.Where(p => p.Name == currentPropertyPath).Single().PropertyType; if (propertyPaths.Count == 1) { var nestedScalarType = nestedPropertyType as QueryScalarType; ExceptionUtilities.CheckObjectNotNull(nestedScalarType, "The leaf property of any structural type must be a scalar type"); var propertyDataSet = dataRows.Select(qsv => qsv.GetValue(currentPropertyPath)); if (propertyDataSet.Count() > 0) { ExceptionUtilities.Assert(propertyDataSet.First() is QueryScalarValue, "Type mismatch between property type and data set, property {0} should be a scalar value in the dataSet", currentPropertyPath); return propertyDataSet.Cast<QueryScalarValue>(); } else { var propertyDataSetList = new List<QueryScalarValue>(); propertyDataSetList.Add(nestedScalarType.DefaultValue as QueryScalarValue); return propertyDataSetList.AsEnumerable<QueryScalarValue>(); } } else { // if we are not at the leaf property, find it recursively. var nestedStructuralType = nestedPropertyType as QueryStructuralType; ExceptionUtilities.CheckObjectNotNull(nestedStructuralType, "A non-leaf property of a structural type must be a structural type"); propertyPaths.RemoveAt(0); var nestedProperties = dataRows.Select(qsv => qsv.GetValue(currentPropertyPath)).Cast<QueryStructuralValue>(); return this.GetPropertyRows(nestedProperties, propertyPaths, nestedStructuralType); } }