/// <summary> /// Check whether the parent and child are properly related types /// </summary> /// <param name="parentType">the parent type</param> /// <param name="childType">the child type</param> /// <exception cref="ODataException">Throws if the two types are not related.</exception> public static void CheckRelatedTo(IEdmType parentType, IEdmType childType) { if (!IsRelatedTo(parentType, childType)) { // If the parentType is an open property, parentType will be null and can't have an ODataFullName. string parentTypeName = (parentType != null) ? parentType.ODataFullName() : "<null>"; throw new ODataException(OData.Core.Strings.MetadataBinder_HierarchyNotFollowed(childType.FullTypeName(), parentTypeName)); } }
/// <summary> /// Translate a TypeSegment /// </summary> /// <param name="segment">the segment to Translate</param> /// <returns>Defined by the implementer</returns> public override string Translate(TypeSegment segment) { Debug.Assert(segment != null, "segment != null"); IEdmType type = segment.EdmType; IEdmCollectionType collectionType = type as IEdmCollectionType; if (collectionType != null) { type = collectionType.ElementType.Definition; } return("/" + type.FullTypeName()); }
public static IEdmOperationParameter AssertHasParameter(this IEdmFunction function, IEdmModel model, string parameterName, Type parameterType, bool isNullable) { IEdmOperationParameter parameter = function.FindParameter(parameterName); Assert.NotNull(parameter); IEdmType edmType = model.GetEdmType(parameterType); Assert.Equal(edmType.FullTypeName(), parameter.Type.FullName()); Assert.Equal(isNullable, parameter.Type.IsNullable); return(parameter); }
private static void SetSwaggerType(Schema obj, IEdmType edmType) { Contract.Requires(obj != null); Contract.Requires(edmType != null); Contract.Assume(edmType.TypeKind != EdmTypeKind.Collection || ((IEdmCollectionType)edmType).ElementType != null); switch (edmType.TypeKind) { case EdmTypeKind.Complex: case EdmTypeKind.Entity: obj.@ref = "#/definitions/" + edmType.FullTypeName(); break; case EdmTypeKind.Primitive: string format; var type = GetPrimitiveTypeAndFormat((IEdmPrimitiveType)edmType, out format); obj.type = type; if (format != null) { obj.format = format; } break; case EdmTypeKind.Enum: obj.type = "string"; break; case EdmTypeKind.Collection: var itemEdmType = ((IEdmCollectionType)edmType).ElementType.GetDefinition(); var nestedItem = new Schema(); SetSwaggerType(nestedItem, itemEdmType); obj.type = "array"; obj.items = nestedItem; break; case EdmTypeKind.None: break; case EdmTypeKind.EntityReference: break; case EdmTypeKind.TypeDefinition: break; default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Handle a TypeSegment, we use "cast" for type segment. /// </summary> /// <param name="segment">the segment to handle</param> public override void Handle(TypeSegment segment) { Contract.Assert(segment != null); _navigationSource = segment.NavigationSource; // Uri literal does not use the collection type. IEdmType elementType = segment.EdmType; if (segment.EdmType.TypeKind == EdmTypeKind.Collection) { elementType = ((IEdmCollectionType)segment.EdmType).ElementType.Definition; } _pathUriLiteral.Add(elementType.FullTypeName()); }
public static Type GetClrType(this IEdmType edmType, ApiBase api) { IEdmModel edmModel = api.GetModelAsync().Result; ClrTypeAnnotation annotation = edmModel.GetAnnotationValue <ClrTypeAnnotation>(edmType); if (annotation != null) { return(annotation.ClrType); } throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Resources.ElementTypeNotFound, edmType.FullTypeName())); }
/// <summary> /// Get the clr type for a specified edm type /// </summary> /// <param name="edmType">The edm type to get clr type</param> /// <param name="serviceProvider">The provider to get service from DI container</param> /// <returns>The clr type</returns> public static Type GetClrType(this IEdmType edmType, IServiceProvider serviceProvider) { var edmModel = serviceProvider.GetService <IEdmModel>(); var annotation = edmModel.GetAnnotationValue <ClrTypeAnnotation>(edmType); if (annotation != null) { return(annotation.ClrType); } throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Resources.ElementTypeNotFound, edmType.FullTypeName())); }
/// <summary> /// Handle a TypeSegment, we use "cast" for type segment. /// </summary> /// <param name="segment">the segment to handle</param> public override void Handle(TypeSegment segment) { _navigationSource = segment.NavigationSource; _pathTemplate.Add(ODataSegmentKinds.Cast); // cast // Uri literal does not use the collection type. IEdmType elementType = segment.EdmType; if (segment.EdmType.TypeKind == EdmTypeKind.Collection) { elementType = ((IEdmCollectionType)segment.EdmType).ElementType.Definition; } _pathUriLiteral.Add(elementType.FullTypeName()); }
public static string ToUriLiteral(this TypeSegment segment) { if (segment == null) { throw Error.ArgumentNull("segment"); } IEdmType elementType = segment.EdmType; if (segment.EdmType.TypeKind == EdmTypeKind.Collection) { elementType = ((IEdmCollectionType)segment.EdmType).ElementType.Definition; } return(elementType.FullTypeName()); }
public static TypeSchema GetSchemaFromModel(IEdmType type) { var structure = type as IEdmStructuredType; if (structure != null) { return(GetSchemaFromModel(structure)); } var collection = type as IEdmCollectionType; if (collection != null) { return(Schema.CreateArray(GetSchemaFromModel(collection.ElementType))); } var primitive = type as IEdmPrimitiveType; if (primitive != null) { switch (primitive.PrimitiveKind) { case EdmPrimitiveTypeKind.Binary: return(Schema.CreateBytes()); case EdmPrimitiveTypeKind.Boolean: return(Schema.CreateBoolean()); case EdmPrimitiveTypeKind.Int32: return(Schema.CreateInt()); case EdmPrimitiveTypeKind.Int64: return(Schema.CreateLong()); case EdmPrimitiveTypeKind.Single: return(Schema.CreateFloat()); case EdmPrimitiveTypeKind.Double: return(Schema.CreateDouble()); case EdmPrimitiveTypeKind.String: return(Schema.CreateString()); } } throw new Exception(string.Format("unsupported type: {0}", type.FullTypeName())); }
/// <summary> /// Get the clr type for a specified edm type. /// </summary> /// <param name="edmType">The edm type to get clr type.</param> /// <param name="edmModel">The edm model.</param> /// <returns>The clr type.</returns> public static Type GetClrType(this IEdmType edmType, IEdmModel edmModel) { Ensure.NotNull(edmType, nameof(edmType)); Ensure.NotNull(edmModel, nameof(edmModel)); var annotation = edmModel.GetAnnotationValue <ClrTypeAnnotation>(edmType); if (annotation != null) { return(annotation.ClrType); } throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Resources.ElementTypeNotFound, edmType.FullTypeName())); }
private IDictionary <string, OpenApiSchema> VisitSchemas() { IDictionary <string, OpenApiSchema> schemas = new Dictionary <string, OpenApiSchema>(); foreach (var element in Model.SchemaElements) { switch (element.SchemaElementKind) { case EdmSchemaElementKind.TypeDefinition: { IEdmType reference = (IEdmType)element; schemas.Add(reference.FullTypeName(), VisitSchemaType(reference)); } break; } } AppendODataErrors(schemas); return(schemas); }
public static Type GetClrType(this IEdmModel edmModel, IEdmType edmType) { if (edmType.TypeKind == EdmTypeKind.Primitive) { return(PrimitiveTypeHelper.GetClrType((edmType as IEdmPrimitiveType).PrimitiveKind)); } OeValueAnnotation <Type> clrTypeAnnotation = edmModel.GetAnnotationValue <OeValueAnnotation <Type> >(edmType); if (clrTypeAnnotation != null) { return(clrTypeAnnotation.Value); } if (edmType is IEdmCollectionType collectionType) { return(edmModel.GetClrType(collectionType.ElementType.Definition)); } throw new InvalidOperationException("Add type annotation for " + edmType.FullTypeName()); }
/// <summary> /// Create the dictionary of <see cref="OpenApiSchema"/> object. /// The name of each pair is the namespace-qualified name of the type. It uses the namespace instead of the alias. /// The value of each pair is a <see cref="OpenApiSchema"/>. /// </summary> /// <param name="context">The OData to Open API context.</param> /// <returns>The string/schema dictionary.</returns> public static IDictionary <string, OpenApiSchema> CreateSchemas(this ODataContext context) { Utils.CheckArgumentNull(context, nameof(context)); IDictionary <string, OpenApiSchema> schemas = new Dictionary <string, OpenApiSchema>(); // Each entity type, complex type, enumeration type, and type definition directly // or indirectly used in the paths field is represented as a name / value pair of the schemas map. // Ideally this would be driven off the types used in the paths, but in practice, it is simply // all of the types present in the model. IEnumerable <IEdmSchemaElement> elements = context.Model.GetAllElements(); foreach (var element in elements) { switch (element.SchemaElementKind) { case EdmSchemaElementKind.TypeDefinition: // Type definition { IEdmType reference = (IEdmType)element; schemas.Add(reference.FullTypeName(), context.CreateSchemaTypeSchema(reference)); } break; } } // append the Edm.Spatial foreach (var schema in context.CreateSpatialSchemas()) { schemas[schema.Key] = schema.Value; } // append the OData errors foreach (var schema in context.CreateODataErrorSchemas()) { schemas[schema.Key] = schema.Value; } return(schemas); }
private static string ConvertBindingPath(EdmTypeMap edmMap, NavigationPropertyBindingConfiguration binding) { IList <string> bindings = new List <string>(); foreach (MemberInfo bindingInfo in binding.Path) { Type typeCast = TypeHelper.AsType(bindingInfo); PropertyInfo propertyInfo = bindingInfo as PropertyInfo; if (typeCast != null) { IEdmType edmType = edmMap.EdmTypes[typeCast]; bindings.Add(edmType.FullTypeName()); } else if (propertyInfo != null) { bindings.Add(edmMap.EdmProperties[propertyInfo].Name); } } return(String.Join("/", bindings)); }
/// <summary> /// Create the dictionary of <see cref="OpenApiSchema"/> object. /// The name of each pair is the namespace-qualified name of the type. It uses the namespace instead of the alias. /// The value of each pair is a <see cref="OpenApiSchema"/>. /// </summary> /// <param name="context">The OData to Open API context.</param> /// <returns>The string/schema dictionary.</returns> public static IDictionary <string, OpenApiSchema> CreateSchemas(this ODataContext context) { Utils.CheckArgumentNull(context, nameof(context)); IDictionary <string, OpenApiSchema> schemas = new Dictionary <string, OpenApiSchema>(); // Each entity type, complex type, enumeration type, and type definition directly // or indirectly used in the paths field is represented as a name / value pair of the schemas map. foreach (var element in context.Model.SchemaElements.Where(c => !c.Namespace.StartsWith("Org.OData."))) { switch (element.SchemaElementKind) { case EdmSchemaElementKind.TypeDefinition: // Type definition { if (CanFilter(context, element)) { IEdmType reference = (IEdmType)element; schemas.Add(reference.FullTypeName(), context.CreateSchemaTypeSchema(reference)); } } break; } } // append the Edm.Spatial foreach (var schema in context.CreateSpatialSchemas()) { schemas[schema.Key] = schema.Value; } // append the OData errors foreach (var schema in context.CreateODataErrorSchemas()) { schemas[schema.Key] = schema.Value; } return(schemas); }
/// <summary> /// Parse from levelsOption token to LevelsClause. /// Negative value would be treated as max. /// </summary> /// <param name="levelsOption">The levelsOption for current expand.</param> /// <param name="sourceType">The type of current level navigation source.</param> /// <param name="property">Navigation property for current expand.</param> /// <returns>The LevelsClause parsed, null if levelsOption is null</returns> private LevelsClause ParseLevels(long? levelsOption, IEdmType sourceType, IEdmNavigationProperty property) { if (!levelsOption.HasValue) { return null; } IEdmType relatedType = property.ToEntityType(); if (sourceType != null && relatedType != null && !UriEdmHelpers.IsRelatedTo(sourceType, relatedType)) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_LevelsNotAllowedOnIncompatibleRelatedType(property.Name, relatedType.FullTypeName(), sourceType.FullTypeName())); } return new LevelsClause(levelsOption.Value < 0, levelsOption.Value); }
/// <summary> /// Create the dictionary of <see cref="OpenApiSchema"/> object. /// The name of each pair is the namespace-qualified name of the type. It uses the namespace instead of the alias. /// The value of each pair is a <see cref="OpenApiSchema"/>. /// </summary> /// <param name="context">The OData to Open API context.</param> /// <returns>The string/schema dictionary.</returns> public static IDictionary <string, OpenApiSchema> CreateSchemas(this ODataContext context) { Utils.CheckArgumentNull(context, nameof(context)); IDictionary <string, OpenApiSchema> schemas = new Dictionary <string, OpenApiSchema>(); // Each entity type, complex type, enumeration type, and type definition directly // or indirectly used in the paths field is represented as a name / value pair of the schemas map. // Ideally this would be driven off the types used in the paths, but in practice, it is simply // all of the types present in the model. IEnumerable <IEdmSchemaElement> elements = context.Model.GetAllElements(); foreach (var element in elements) { switch (element.SchemaElementKind) { case EdmSchemaElementKind.TypeDefinition: // Type definition { IEdmType reference = (IEdmType)element; var fullTypeName = reference.FullTypeName(); if (reference is IEdmComplexType && fullTypeName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries) .Last() .Equals(context.Settings.InnerErrorComplexTypeName, StringComparison.Ordinal)) { continue; } schemas.Add(fullTypeName, context.CreateSchemaTypeSchema(reference)); } break; } } // append the Edm.Spatial foreach (var schema in context.CreateSpatialSchemas()) { schemas[schema.Key] = schema.Value; } // append the OData errors foreach (var schema in context.CreateODataErrorSchemas()) { schemas[schema.Key] = schema.Value; } if (context.Settings.EnableDollarCountPath) { schemas[Constants.DollarCountSchemaName] = new OpenApiSchema { Type = "integer", Format = "int32" } } ; schemas = schemas.Concat(context.GetAllCollectionEntityTypes() .Select(x => new KeyValuePair <string, OpenApiSchema>( $"{(x is IEdmEntityType eType ? eType.FullName() : x.FullTypeName())}{Constants.CollectionSchemaSuffix}", CreateCollectionSchema(context, x))) .Where(x => !schemas.ContainsKey(x.Key))) .Concat(context.GetAllCollectionComplexTypes() .Select(x => new KeyValuePair <string, OpenApiSchema>( $"{x.FullTypeName()}{Constants.CollectionSchemaSuffix}", CreateCollectionSchema(context, x))) .Where(x => !schemas.ContainsKey(x.Key))) .ToDictionary(x => x.Key, x => x.Value); if (context.HasAnyNonContainedCollections()) { schemas[$"String{Constants.CollectionSchemaSuffix}"] = CreateCollectionSchema(context, new OpenApiSchema { Type = "string" }, "string"); } schemas[Constants.ReferenceUpdateSchemaName] = new() { Type = "object", Properties = new Dictionary <string, OpenApiSchema> { { Constants.OdataId, new OpenApiSchema { Type = "string", Nullable = false } }, { Constants.OdataType, new OpenApiSchema { Type = "string", Nullable = true } }, } }; schemas[Constants.ReferenceCreateSchemaName] = new() { Type = "object", Properties = new Dictionary <string, OpenApiSchema> { { Constants.OdataId, new OpenApiSchema { Type = "string", Nullable = false } } }, AdditionalProperties = new OpenApiSchema { Type = "object" } }; return(schemas); } internal static bool HasAnyNonContainedCollections(this ODataContext context)
public static object CreateResource(IEdmType type) { var targetType = EdmClrTypeUtils.GetInstanceType(type.FullTypeName()); return QuickCreateInstance(targetType); }
/// <summary> /// Getting the instance type from the assembly in name /// </summary> /// <param name="assembly"></param> /// <param name="type"></param> /// <returns></returns> private static Type GetInstanceType(IEdmType type, string typeName) { Type result = null; switch (type.TypeKind) { case EdmTypeKind.Enum: result = GetTypeFromModels(typeName); if (result != null && !result.IsEnum) { throw new InvalidOperationException( string.Format("The EdmType {0} is not match to the instance type {1}.", type.FullTypeName(), result.FullName)); } break; case EdmTypeKind.Entity: result = GetTypeFromModels(typeName); // TODO: Validate the type is a entity type. break; case EdmTypeKind.Complex: result = GetTypeFromModels(typeName); // TODO: Validate the type is a complex type. break; case EdmTypeKind.Collection: var elementType = GetTypeFromModels((type as IEdmCollectionType).ElementType.Definition.FullTypeName()); result = typeof(List <>).MakeGenericType(new[] { elementType }); break; // It seems we never hit here. default: throw new InvalidOperationException(string.Format("GetInstanceType for TypeKind {0} is not supported.", type.TypeKind)); } return(result); }
/// <summary> /// Try to bind namespace-qualified type cast segment. /// </summary> internal static bool TryBindTypeCastSegment(string identifier, string parenthesisExpressions, IEdmModel model, IList <PathSegment> path, PathParserSettings settings) { if (identifier == null || identifier.IndexOf('.') < 0) { // type cast should be namespace-qualified name return(false); } PathSegment preSegment = path.LastOrDefault(); if (preSegment == null) { // type cast should not be the first segment. return(false); } IEdmSchemaType schemaType = model.ResolveType(identifier, settings.EnableCaseInsensitive); if (schemaType == null) { return(false); } IEdmType targetEdmType = schemaType as IEdmType; if (targetEdmType == null) { return(false); } IEdmType previousEdmType = preSegment.EdmType; bool isNullable = false; if (previousEdmType.TypeKind == EdmTypeKind.Collection) { previousEdmType = ((IEdmCollectionType)previousEdmType).ElementType.Definition; isNullable = ((IEdmCollectionType)previousEdmType).ElementType.IsNullable; } if (!targetEdmType.IsOrInheritsFrom(previousEdmType) && !previousEdmType.IsOrInheritsFrom(targetEdmType)) { throw new Exception($"Type cast {targetEdmType.FullTypeName()} has no relationship with previous {previousEdmType.FullTypeName()}."); } // We want the type of the type segment to be a collection if the previous segment was a collection IEdmType actualTypeOfTheTypeSegment = targetEdmType; if (preSegment.EdmType.TypeKind == EdmTypeKind.Collection) { var actualEntityTypeOfTheTypeSegment = targetEdmType as IEdmEntityType; if (actualEntityTypeOfTheTypeSegment != null) { actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmEntityTypeReference(actualEntityTypeOfTheTypeSegment, isNullable)); } else { // Complex collection supports type cast too. var actualComplexTypeOfTheTypeSegment = actualTypeOfTheTypeSegment as IEdmComplexType; if (actualComplexTypeOfTheTypeSegment != null) { actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmComplexTypeReference(actualComplexTypeOfTheTypeSegment, isNullable)); } else { throw new Exception($"Invalid type cast of {identifier}, it should be entity or complex."); } } } TypeSegment typeCast = new TypeSegment(actualTypeOfTheTypeSegment, preSegment.EdmType, preSegment.NavigationSource, identifier); path.Add(typeCast); TryBindKeySegment(parenthesisExpressions, path); return(true); }
/// <summary> /// Resolves the payload type versus the expected type and validates that such combination is allowed when strict validation is enabled. /// </summary> /// <param name="expectedTypeKind">The expected type kind for the value.</param> /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param> /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param> /// <returns>The target type reference to use for parsing the value.</returns> private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationEnabled( EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType) { // Strict validation logic switch (expectedTypeKind) { case EdmTypeKind.Complex: if (payloadType != null) { // The payload type must be compatible to the expected type. VerifyComplexType(expectedTypeReference, payloadType, /* failIfNotRelated */ true); // Use the payload type return payloadType.ToTypeReference(/*nullable*/ true); } break; case EdmTypeKind.Entity: if (payloadType != null) { // The payload type must be assignable to the expected type. IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true); ValidationUtils.ValidateEntityTypeIsAssignable((IEdmEntityTypeReference)expectedTypeReference, (IEdmEntityTypeReference)payloadTypeReference); // Use the payload type return payloadTypeReference; } break; case EdmTypeKind.Enum: if (payloadType != null && string.CompareOrdinal(payloadType.FullTypeName(), expectedTypeReference.FullName()) != 0) { throw new ODataException(Strings.ValidationUtils_IncompatibleType(payloadType.FullTypeName(), expectedTypeReference.FullName())); } break; case EdmTypeKind.Collection: // The type must be exactly equal - note that we intentionally ignore nullability of the items here, since the payload type // can't specify that. if (payloadType != null && !payloadType.IsElementTypeEquivalentTo(expectedTypeReference.Definition)) { VerifyCollectionComplexItemType(expectedTypeReference, payloadType); throw new ODataException(Strings.ValidationUtils_IncompatibleType(payloadType.FullTypeName(), expectedTypeReference.FullName())); } break; case EdmTypeKind.TypeDefinition: if (payloadType != null && !expectedTypeReference.Definition.IsAssignableFrom(payloadType)) { throw new ODataException(Strings.ValidationUtils_IncompatibleType(payloadType.FullTypeName(), expectedTypeReference.FullName())); } break; default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind)); } // Either there's no payload type, in which case use the expected one, or the payload one and the expected one are equal. return expectedTypeReference; }
/// <summary> /// Resolves the given type if a client type resolver is available. /// </summary> /// <param name="typeToResolve">Type to resolve.</param> /// <returns>The resolved type.</returns> private IEdmType ResolveType(IEdmType typeToResolve) { Debug.Assert(typeToResolve != null, "typeToResolve != null"); Debug.Assert(this.model != null, "model != null"); Debug.Assert(this.readerBehavior != null, "readerBehavior != null"); Func<IEdmType, string, IEdmType> customTypeResolver = this.readerBehavior.TypeResolver; if (customTypeResolver == null) { return typeToResolve; } Debug.Assert(this.readerBehavior.ApiBehaviorKind == ODataBehaviorKind.WcfDataServicesClient, "Custom type resolver can only be specified in WCF DS Client behavior."); EdmTypeKind typeKind; // MetadataUtils.ResolveTypeName() does not allow entity collection types however both operationImport.ReturnType and operationParameter.Type can be of entity collection types. // We don't want to relax MetadataUtils.ResolveTypeName() since the rest of ODL only allows primitive and complex collection types and is currently relying on the method to // enforce this. So if typeToResolve is an entity collection type, we will resolve the item type and reconstruct the collection type from the resolved item type. IEdmCollectionType collectionTypeToResolve = typeToResolve as IEdmCollectionType; if (collectionTypeToResolve != null && collectionTypeToResolve.ElementType.IsEntity()) { IEdmTypeReference itemTypeReferenceToResolve = collectionTypeToResolve.ElementType; IEdmType resolvedItemType = MetadataUtils.ResolveTypeName(this.model, null /*expectedType*/, itemTypeReferenceToResolve.FullName(), customTypeResolver, out typeKind); return new EdmCollectionType(resolvedItemType.ToTypeReference(itemTypeReferenceToResolve.IsNullable)); } return MetadataUtils.ResolveTypeName(this.model, null /*expectedType*/, typeToResolve.FullTypeName(), customTypeResolver, out typeKind); }
/// <summary> /// Getting the instance type from the assembly in name /// </summary> /// <param name="assembly"></param> /// <param name="type"></param> /// <returns></returns> private static Type GetInstanceType(IEdmType type, string typeName) { Type result = null; switch (type.TypeKind) { case EdmTypeKind.Enum: result = GetTypeFromModels(typeName); if (result != null && !result.IsEnum) { throw new InvalidOperationException( string.Format("The EdmType {0} is not match to the instance type {1}.", type.FullTypeName(), result.FullName)); } break; case EdmTypeKind.Entity: result = GetTypeFromModels(typeName); // TODO: Validate the type is a entity type. break; case EdmTypeKind.Complex: result = GetTypeFromModels(typeName); // TODO: Validate the type is a complex type. break; case EdmTypeKind.Collection: var elementType = GetTypeFromModels((type as IEdmCollectionType).ElementType.Definition.FullTypeName()); result = typeof (List<>).MakeGenericType(new[] {elementType}); break; // It seems we never hit here. default: throw new InvalidOperationException(string.Format("GetInstanceType for TypeKind {0} is not supported.", type.TypeKind)); } return result; }
/// <summary> /// Calculates the operations that are bindable to the given type. /// </summary> /// <param name="bindingType">The binding type in question.</param> /// <param name="model">The model to search for operations.</param> /// <param name="edmTypeResolver">The edm type resolver to get the parameter type.</param> /// <returns>An enumeration of operations that are always bindable to the given type.</returns> internal static IList <IEdmOperation> CalculateBindableOperationsForType(IEdmType bindingType, IEdmModel model, EdmTypeResolver edmTypeResolver) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmTypeResolver != null, "edmTypeResolver != null"); IEnumerable <IEdmOperation> operations = null; try { operations = model.FindBoundOperations(bindingType); } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } throw new ODataException(Strings.MetadataUtils_CalculateBindableOperationsForType(bindingType.FullTypeName()), exc); } IList <IEdmOperation> operationsFound = operations as IList <IEdmOperation>; if (operationsFound != null) { return(operationsFound); } operationsFound = new List <IEdmOperation>(operations); return(operationsFound); }
/// <summary> /// Calculates the operations that are bindable to the given type. /// </summary> /// <param name="bindingType">The binding type in question.</param> /// <param name="model">The model to search for operations.</param> /// <param name="edmTypeResolver">The edm type resolver to get the parameter type.</param> /// <returns>An enumeration of operations that are always bindable to the given type.</returns> internal static IList <IEdmOperation> CalculateBindableOperationsForType(IEdmType bindingType, IEdmModel model, EdmTypeResolver edmTypeResolver) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmTypeResolver != null, "edmTypeResolver != null"); IEnumerable <IEdmOperation> operations = null; try { operations = model.FindBoundOperations(bindingType); } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } throw new ODataException(Strings.MetadataUtils_CalculateBindableOperationsForType(bindingType.FullTypeName()), exc); } List <IEdmOperation> operationsFound = new List <IEdmOperation>(); foreach (IEdmOperation operation in operations) { if (!operation.IsBound) { throw new ODataException(Strings.EdmLibraryExtensions_UnBoundOperationsFoundFromIEdmModelFindMethodIsInvalid(operation.Name)); } if (operation.Parameters.FirstOrDefault() == null) { throw new ODataException(Strings.EdmLibraryExtensions_NoParameterBoundOperationsFoundFromIEdmModelFindMethodIsInvalid(operation.Name)); } IEdmOperationParameter bindingParameter = operation.Parameters.FirstOrDefault(); IEdmType resolvedBindingType = edmTypeResolver.GetParameterType(bindingParameter).Definition; if (resolvedBindingType.IsAssignableFrom(bindingType)) { operationsFound.Add(operation); } } return(operationsFound); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- private Type TranslateEdmTypeToClrType(IEdmModel model, IEdmType edmType) { var annotation = model.GetAnnotationValue<ClrTypeAnnotation>(edmType); if ( annotation != null ) { return annotation.ClrType; } var entityType = (edmType as IEdmEntityType); if ( entityType != null ) { return base.Context.Factory.FindDynamicType(new EdmEntityTypeKey(model, entityType)); } var collectionType = (edmType as IEdmCollectionType); if ( collectionType != null ) { var elementClrType = TranslateEdmTypeToClrType(model, collectionType.ElementType.Definition); return typeof (DataServiceCollection<>).MakeGenericType(elementClrType); } var primitiveType = (edmType as IEdmPrimitiveType); if ( primitiveType != null ) { return s_BuiltInTypesMapping[primitiveType]; } throw new Exception("Could not determine CLR type for EDM type: " + edmType.FullTypeName() + " {" + edmType.GetType().Name + "}"); }
/// <summary> /// Java specific function that infers the return type for java that is going to be returned /// </summary> /// <param name="edmType">Definition of the type from the OData model</param> /// <param name="typeHint">Hint of the variable name that is coming back</param> /// <returns>String representing the return type</returns> private static string GetJavaReturnTypeName(IEdmType edmType, string typeHint) { var typeName = string.Empty; if (edmType is IEdmCollectionType collectionType) { if (collectionType.ElementType.Definition is IEdmNamedElement edmNamedElement) { typeName = typeHint.Equals("delta", StringComparison.OrdinalIgnoreCase) ? $"I{CommonGenerator.UppercaseFirstLetter(edmNamedElement.Name)}DeltaCollectionPage" : $"I{CommonGenerator.UppercaseFirstLetter(edmNamedElement.Name)}CollectionPage"; } else { typeName = $"I{typeName}CollectionPage"; } } else { typeName = edmType == null ? "Content": CommonGenerator.UppercaseFirstLetter(edmType.FullTypeName().Split(".").Last()); } return(typeName); }
public static void SetSwaggerType(JObject jObject, IEdmType edmType) { if (edmType.TypeKind == EdmTypeKind.Complex || edmType.TypeKind == EdmTypeKind.Entity) { jObject.Add("$ref", "#/definitions/" + edmType.FullTypeName()); } else if (edmType.TypeKind == EdmTypeKind.Primitive) { string format; string type = GetPrimitiveTypeAndFormat((IEdmPrimitiveType) edmType, out format); jObject.Add("type", type); if (format != null) { jObject.Add("format", format); } } else if (edmType.TypeKind == EdmTypeKind.Enum) { jObject.Add("type", "string"); } else if (edmType.TypeKind == EdmTypeKind.Collection) { IEdmType itemEdmType = ((IEdmCollectionType)edmType).ElementType.Definition; JObject nestedItem = new JObject(); SetSwaggerType(nestedItem, itemEdmType); jObject.Add("type", "array"); jObject.Add("items", nestedItem); } }
/// <summary> /// Applies the model and validates the context URI against it. /// </summary> /// <param name="expectedPayloadKind">The payload kind we expect the context URI to conform to.</param> /// <param name="clientCustomTypeResolver">The function of client custom type resolver.</param> /// <param name="throwIfMetadataConflict">Whether to throw if a type specified in the ContextUri is not found in metadata.</param> private void ParseContextUri(ODataPayloadKind expectedPayloadKind, Func <IEdmType, string, IEdmType> clientCustomTypeResolver, bool throwIfMetadataConflict) { bool isUndeclared; ODataPayloadKind detectedPayloadKind = this.ParseContextUriFragment(this.parseResult.Fragment, clientCustomTypeResolver, throwIfMetadataConflict, out isUndeclared); // unsupported payload kind indicates that this is during payload kind detection, so we should not fail. bool detectedPayloadKindMatchesExpectation = detectedPayloadKind == expectedPayloadKind || expectedPayloadKind == ODataPayloadKind.Unsupported; IEdmType parseType = this.parseResult.EdmType; if (parseType != null && parseType.TypeKind == EdmTypeKind.Untyped) { if (string.Equals(parseType.FullTypeName(), ODataConstants.ContextUriFragmentUntyped, StringComparison.Ordinal)) { // Anything matches the built-in Edm.Untyped this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.ResourceSet, ODataPayloadKind.Property, ODataPayloadKind.Collection, ODataPayloadKind.Resource }; detectedPayloadKindMatchesExpectation = true; } else if (expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Resource) { // If we created an untyped type because the name was not resolved it can match any single value this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Property, ODataPayloadKind.Resource }; detectedPayloadKindMatchesExpectation = true; } } else if (parseType != null && parseType.TypeKind == EdmTypeKind.Collection && ((IEdmCollectionType)parseType).ElementType.TypeKind() == EdmTypeKind.Untyped) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.ResourceSet, ODataPayloadKind.Property, ODataPayloadKind.Collection }; if (expectedPayloadKind == ODataPayloadKind.ResourceSet || expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Collection) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.ResourceSet && parseType.IsODataComplexTypeKind()) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.ResourceSet, ODataPayloadKind.Property, ODataPayloadKind.Collection }; if (expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Collection) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Resource && parseType.IsODataComplexTypeKind()) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Resource, ODataPayloadKind.Property }; if (expectedPayloadKind == ODataPayloadKind.Property) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Collection) { // If the detected payload kind is 'collection' it can always also be treated as a property. this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Collection, ODataPayloadKind.Property }; if (expectedPayloadKind == ODataPayloadKind.Property) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Resource) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Resource, ODataPayloadKind.Delta }; if (expectedPayloadKind == ODataPayloadKind.Delta) { this.parseResult.DeltaKind = ODataDeltaKind.Resource; detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Property && isUndeclared && (expectedPayloadKind == ODataPayloadKind.Resource || expectedPayloadKind == ODataPayloadKind.ResourceSet)) { // for undeclared, we don't know whether it is a resource/resource set or not. this.parseResult.DetectedPayloadKinds = new[] { expectedPayloadKind, ODataPayloadKind.Property }; detectedPayloadKindMatchesExpectation = true; } else { this.parseResult.DetectedPayloadKinds = new[] { detectedPayloadKind }; } // If the expected and detected payload kinds don't match and we are not running payload kind detection // right now (payloadKind == ODataPayloadKind.Unsupported) and we did not detect a collection kind for // an expected property kind (which is allowed), fail. if (!detectedPayloadKindMatchesExpectation) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_ContextUriDoesNotMatchExpectedPayloadKind(UriUtils.UriToString(this.parseResult.ContextUri), expectedPayloadKind.ToString())); } // NOTE: we interpret an empty select query option to mean that nothing should be projected // (whereas a missing select query option means everything should be projected). string selectQueryOption = this.parseResult.SelectQueryOption; if (selectQueryOption != null) { if (detectedPayloadKind != ODataPayloadKind.ResourceSet && detectedPayloadKind != ODataPayloadKind.Resource && detectedPayloadKind != ODataPayloadKind.Delta) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidPayloadKindWithSelectQueryOption(expectedPayloadKind.ToString())); } } }
protected static Type GetType(IEdmType type) { var mappingAssembly = typeof(Person).Assembly; // TODO: ??? return(mappingAssembly.GetType(type.FullTypeName())); }
/// <summary> /// Validates that the observed type kind is the expected type kind. /// </summary> /// <param name="actualTypeKind">The actual type kind.</param> /// <param name="expectedTypeKind">The expected type kind.</param> /// <param name="expectStructuredType">This value indicates if the <paramref name="actualTypeKind"/> is expected to be complex or entity. /// True for complex or entity, false for non-structured type kind, null for indetermination.</param> /// <param name="edmType">The edm type to use in the error.</param> /// <remarks>If expectedStructuredType is true, then expectedTypeKind could be </remarks> public virtual void ValidateTypeKind(EdmTypeKind actualTypeKind, EdmTypeKind expectedTypeKind, bool?expectStructuredType, IEdmType edmType) { if (settings.ThrowIfTypeConflictsWithMetadata) { ValidationUtils.ValidateTypeKind( actualTypeKind, expectedTypeKind, expectStructuredType, edmType == null ? null : edmType.FullTypeName()); } }
public static TypeSchema GetSchemaFromModel(IEdmType type) { var structure = type as IEdmStructuredType; if (structure != null) { return GetSchemaFromModel(structure); } var collection = type as IEdmCollectionType; if (collection != null) { return Schema.CreateArray(GetSchemaFromModel(collection.ElementType)); } var primitive = type as IEdmPrimitiveType; if (primitive != null) { switch (primitive.PrimitiveKind) { case EdmPrimitiveTypeKind.Binary: return Schema.CreateBytes(); case EdmPrimitiveTypeKind.Boolean: return Schema.CreateBoolean(); case EdmPrimitiveTypeKind.Int32: return Schema.CreateInt(); case EdmPrimitiveTypeKind.Int64: return Schema.CreateLong(); case EdmPrimitiveTypeKind.Single: return Schema.CreateFloat(); case EdmPrimitiveTypeKind.Double: return Schema.CreateDouble(); case EdmPrimitiveTypeKind.String: return Schema.CreateString(); } } throw new Exception(string.Format("unsupported type: {0}", type.FullTypeName())); }
/// <summary> /// Validates the type of a resource in a top-level resource set. /// </summary> /// <param name="itemType">The type of the resource.</param> internal void ValidateResource(IEdmType itemType) { if (this.itemType == null || this.itemType.TypeKind == EdmTypeKind.Untyped) { return; } // If we don't have a type, store the type of the first item. if (this.itemType == null) { this.itemType = itemType; } // Validate the expected and actual types. if (this.itemType.IsEquivalentTo(itemType)) { return; } IEdmStructuredType structuredType = itemType as IEdmStructuredType; IEdmStructuredType thisStructuredType = this.itemType as IEdmStructuredType; if (structuredType == null || thisStructuredType == null) { throw new ODataException(Strings.ResourceSetWithoutExpectedTypeValidator_IncompatibleTypes(itemType.FullTypeName(), this.itemType.FullTypeName())); } // If the types are not equivalent, make sure they have a common base type. IEdmType commonBaseType = EdmLibraryExtensions.GetCommonBaseType(thisStructuredType, structuredType); if (commonBaseType == null) { throw new ODataException(Strings.ResourceSetWithoutExpectedTypeValidator_IncompatibleTypes(itemType.FullTypeName(), this.itemType.FullTypeName())); } this.itemType = (IEdmType)commonBaseType; }
internal static IEdmOperation[] CalculateBindableOperationsForType(IEdmType bindingType, IEdmModel model, EdmTypeResolver edmTypeResolver) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmTypeResolver != null, "edmTypeResolver != null"); List <IEdmOperation> operations = null; try { operations = model.FindBoundOperations(bindingType).ToList(); } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } throw new ODataException(Strings.MetadataUtils_CalculateBindableOperationsForType(bindingType.FullTypeName()), exc); } List <IEdmOperation> operationsFound = new List <IEdmOperation>(); foreach (IEdmOperation operation in operations.EnsureOperationsBoundWithBindingParameter()) { IEdmOperationParameter bindingParameter = operation.Parameters.FirstOrDefault(); IEdmType resolvedBindingType = edmTypeResolver.GetParameterType(bindingParameter).Definition; if (resolvedBindingType.IsAssignableFrom(bindingType)) { operationsFound.Add(operation); } } return(operationsFound.ToArray()); }
/// <summary> /// Parse from levelsOption token to LevelsClause. /// Negative value would be treated as max. /// </summary> /// <param name="levelsOption">The levelsOption for current expand.</param> /// <param name="sourceType">The type of current level navigation source.</param> /// <param name="property">Navigation property for current expand.</param> /// <returns>The LevelsClause parsed, null if levelsOption is null</returns> private static LevelsClause ParseLevels(long?levelsOption, IEdmType sourceType, IEdmNavigationProperty property) { if (!levelsOption.HasValue) { return(null); } IEdmType relatedType = property.ToEntityType(); if (sourceType != null && relatedType != null && !UriEdmHelpers.IsRelatedTo(sourceType, relatedType)) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_LevelsNotAllowedOnIncompatibleRelatedType(property.Name, relatedType.FullTypeName(), sourceType.FullTypeName())); } return(new LevelsClause(levelsOption.Value < 0, levelsOption.Value)); }
internal static IEdmOperation[] CalculateBindableOperationsForType(IEdmType bindingType, IEdmModel model, EdmTypeResolver edmTypeResolver) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmTypeResolver != null, "edmTypeResolver != null"); List<IEdmOperation> operations = null; try { operations = model.FindBoundOperations(bindingType).ToList(); } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } throw new ODataException(Strings.MetadataUtils_CalculateBindableOperationsForType(bindingType.FullTypeName()), exc); } List<IEdmOperation> operationsFound = new List<IEdmOperation>(); foreach (IEdmOperation operation in operations.EnsureOperationsBoundWithBindingParameter()) { IEdmOperationParameter bindingParameter = operation.Parameters.FirstOrDefault(); IEdmType resolvedBindingType = edmTypeResolver.GetParameterType(bindingParameter).Definition; if (resolvedBindingType.IsAssignableFrom(bindingType)) { operationsFound.Add(operation); } } return operationsFound.ToArray(); }
public static object CreateResource(IEdmType type) { var targetType = EdmClrTypeUtils.GetInstanceType(type.FullTypeName()); return(QuickCreateInstance(targetType)); }
/// <summary> /// Initializes a new instance of <see cref="TypeSegment"/> class. /// </summary> /// <param name="actualType">The actual type, from the Uri.</param> /// <param name="expectedType">The expected type, from the Edm model.</param> /// <param name="navigationSource">The navigation source.</param> public TypeSegment(IEdmType actualType, IEdmType expectedType, IEdmNavigationSource navigationSource) : this(actualType, expectedType, navigationSource, actualType?.FullTypeName()) { }