private static IEnumerable<IEdmOperation> GetMatchedOperations(this IEnumerable<IEdmOperation> operations, string operationIdentifier, IEdmType bindingType) { Contract.Assert(operations != null); Contract.Assert(operationIdentifier != null); Contract.Assert(bindingType != null); string[] nameParts = operationIdentifier.Split('.'); Contract.Assert(nameParts.Length != 0); if (nameParts.Length == 1) { // Name string name = nameParts[0]; operations = operations.Where(f => f.Name == name); } else { // Namespace.Name string name = nameParts[nameParts.Length - 1]; string nspace = String.Join(".", nameParts.Take(nameParts.Length - 1)); operations = operations.Where(f => f.Name == name && f.Namespace == nspace); } return operations.Where(procedure => procedure.CanBindTo(bindingType)); }
/// <summary> /// Sets the single instance of <see cref="ClientTypeAnnotation"/> on the given instance of <paramref name="edmType"/>. /// </summary> /// <param name="model">The model the <paramref name="edmType"/> belongs to.</param> /// <param name="edmType">IEdmType instance to set the annotation on.</param> /// <param name="annotation">The annotation to set</param> internal static void SetClientTypeAnnotation(this IEdmModel model, IEdmType edmType, ClientTypeAnnotation annotation) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmType != null, "edmType != null"); Debug.Assert(annotation != null, "annotation != null"); model.SetAnnotationValue<ClientTypeAnnotation>(edmType, annotation); }
/// <summary> /// Gets the single instance of <see cref="ClientTypeAnnotation"/> from the given instance of <paramref name="edmType"/>. /// </summary> /// <param name="model">The model the <paramref name="edmType"/> belongs to.</param> /// <param name="edmType">IEdmType instance to get the annotation.</param> /// <returns>Returns the single instance of <see cref="ClientTypeAnnotation"/> from the given instance of <paramref name="edmType"/>.</returns> internal static ClientTypeAnnotation GetClientTypeAnnotation(this IEdmModel model, IEdmType edmType) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmType != null, "edmType != null"); return model.GetAnnotationValue<ClientTypeAnnotation>(edmType); }
private static IEdmTypeReference GetPropertyType(IEdmType type, string propertyName) { IEdmStructuredType type2 = type as IEdmStructuredType; IEdmProperty property = (type2 == null) ? null : type2.FindProperty(propertyName); if (property != null) { IEdmTypeReference typeReference = property.Type; if (typeReference.IsNonEntityODataCollectionTypeKind()) { throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, type.ODataFullName())); } if (typeReference.IsStream()) { throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_StreamPropertyCannotBeMapped(propertyName, type.ODataFullName())); } if (typeReference.IsSpatial()) { throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, type.ODataFullName())); } return property.Type; } if ((type != null) && !type.IsOpenType()) { throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_MissingPropertyOnType(propertyName, type.ODataFullName())); } return null; }
internal static IEdmTypeReference ResolveAndValidateNonPrimitiveTargetType(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, EdmTypeKind payloadTypeKind, IEdmType payloadType, string payloadTypeName, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, out SerializationTypeNameAnnotation serializationTypeNameAnnotation) { bool flag = (messageReaderSettings.ReaderBehavior.TypeResolver != null) && (payloadType != null); if (!flag) { ValidateTypeSupported(expectedTypeReference, version); if (model.IsUserModel() && ((expectedTypeReference == null) || !messageReaderSettings.DisableStrictMetadataValidation)) { VerifyPayloadTypeDefined(payloadTypeName, payloadType); } } else { ValidateTypeSupported((payloadType == null) ? null : payloadType.ToTypeReference(true), version); } if ((payloadTypeKind != EdmTypeKind.None) && (!messageReaderSettings.DisableStrictMetadataValidation || (expectedTypeReference == null))) { ValidationUtils.ValidateTypeKind(payloadTypeKind, expectedTypeKind, payloadTypeName); } serializationTypeNameAnnotation = null; if (!model.IsUserModel()) { return null; } if ((expectedTypeReference == null) || flag) { return ResolveAndValidateTargetTypeWithNoExpectedType(expectedTypeKind, payloadType, payloadTypeName, out serializationTypeNameAnnotation); } if (messageReaderSettings.DisableStrictMetadataValidation) { return ResolveAndValidateTargetTypeStrictValidationDisabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation); } return ResolveAndValidateTargetTypeStrictValidationEnabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation); }
public override IEnumerable<IEdmOperation> ResolveBoundOperations( IEdmModel model, string identifier, IEdmType bindingType) { return unqualified.ResolveBoundOperations(model, identifier, bindingType); }
/// <summary> /// Throws if the type is not related to the type of the given set. /// </summary> /// <param name="type">Type to check.</param> /// <param name="secondType">Second type, which should be related to the first type.</param> /// <param name="segmentName">The segment that is checking this.</param> internal static void ThrowIfTypesUnrelated(IEdmType type, IEdmType secondType, string segmentName) { if (!UriEdmHelpers.IsRelatedTo(type.AsElementType(), secondType)) { throw new ODataException(Strings.PathParser_TypeMustBeRelatedToSet(type, secondType, segmentName)); } }
/// <summary> /// Initializes a new instance of the <see cref="EdmTypeReference"/> class. /// </summary> /// <param name="definition">Type that describes this value.</param> /// <param name="isNullable">Denotes whether the type can be nullable.</param> protected EdmTypeReference(IEdmType definition, bool isNullable) { EdmUtil.CheckArgumentNull(definition, "definition"); this.definition = definition; this.isNullable = isNullable; }
public static AndConstraint<IEdmType> ShouldBeEquivalentTo(this IEdmType type, IEdmType expectedType) { type.IsEquivalentTo(expectedType).Should().BeTrue(); ////typeReference.Should().BeSameAs(expectedTypeReference.Definition); ////typeReference.IsNullable.Should().Be(expectedTypeReference.IsNullable); return new AndConstraint<IEdmType>(type); }
public TypeSchema UpdateSchema(object value, IEdmType edmType, bool collection = false) { TypeSchema schema = null; if (edmType != null) { try { schema = ODataAvroSchemaGen.GetSchemaFromModel(edmType); } catch (ApplicationException) { } } if (schema == null) { if (value == null) { return null; } schema = ODataAvroSchemaGen.GetSchema(value); } TypeSchema single = AvroSerializer.CreateGeneric(schema.ToString()).WriterSchema; if (collection) { schema = ODataAvroSchemaGen.GetArraySchema(schema); single = ((ArraySchema)AvroSerializer.CreateGeneric(schema.ToString()).WriterSchema).ItemSchema; } var writer = AvroContainer.CreateGenericWriter(schema.ToString(), stream, true, Codec.Null); this.seqWriter = new SequentialWriter<object>(writer, 16); return single; }
private static IEdmTypeReference GetNullablePayloadTypeReference(IEdmType payloadType) { if (payloadType != null) { return payloadType.ToTypeReference(true); } return null; }
public ParserExtModel() { Person = (IEdmEntityType)Model.FindType("TestNS.Person"); Pet = Model.FindType("TestNS.Pet"); Fish = Model.FindType("TestNS.Fish"); People = Model.FindDeclaredEntitySet("People"); PetSet = Model.FindDeclaredEntitySet("PetSet"); }
internal ClientTypeAnnotation(IEdmType edmType, Type type, string qualifiedName, DataServiceProtocolVersion maxProtocolVersion) { this.EdmType = edmType; this.ElementTypeName = qualifiedName; this.ElementType = Nullable.GetUnderlyingType(type) ?? type; this.MaxProtocolVersion = maxProtocolVersion; this.epmLazyLoader = new EpmLazyLoader(this); }
/// <summary>Constructor, creates a new resource with preinitialized properties.</summary> /// <param name="resourceType">The type of the resource to create.</param> /// <param name="values">The properties to initialize.</param> public DSPResource(IEdmType resourceType, IEnumerable<KeyValuePair<string, object>> values) : this(resourceType) { foreach (var value in values) { this.properties.Add(value.Key, value.Value); } }
protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment) { if (segment == "$count") { return new CountPathSegment(); } return base.ParseAtEntityCollection(model, previous, previousEdmType, segment); }
/// <summary> /// Gets the EDM type for this segment. /// </summary> /// <param name="previousEdmType">The EDM type of the previous path segment.</param> /// <returns> /// The EDM type for this segment. /// </returns> public override IEdmType GetEdmType(IEdmType previousEdmType) { if (Property != null) { return Property.Type.Definition; } return null; }
/// <summary> /// Gets the EDM type for this segment. /// </summary> /// <param name="previousEdmType">The EDM type of the previous path segment.</param> /// <returns> /// The EDM type for this segment. /// </returns> public override IEdmType GetEdmType(IEdmType previousEdmType) { if (EntitySet != null) { return EntitySet.ElementType.GetCollection(); } return null; }
/// <summary> /// Gets the EDM type for this segment. /// </summary> /// <param name="previousEdmType">The EDM type of the previous path segment.</param> /// <returns> /// The EDM type for this segment. /// </returns> public override IEdmType GetEdmType(IEdmType previousEdmType) { IEdmCollectionType previousCollectionType = previousEdmType as IEdmCollectionType; if (previousCollectionType != null) { return previousCollectionType.ElementType.Definition; } return null; }
/// <summary> /// Gets the EDM type for this segment. /// </summary> /// <param name="previousEdmType">The EDM type of the previous path segment.</param> /// <returns> /// The EDM type for this segment. /// </returns> public override IEdmType GetEdmType(IEdmType previousEdmType) { if (EntitySetBase != null) { return EntitySetBase.EntityType().GetCollection(); } return null; }
/// <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)); } }
/// <inheritdoc/> public override IEdmType GetEdmType(IEdmType previousEdmType) { if (Singleton != null) { return Singleton.EntityType(); } return null; }
public static IEnumerable<IEdmOperation> FindMatchedOperations(this IEdmModel model, string identifier, IEdmType bindingType) { Contract.Assert(model != null); Contract.Assert(identifier != null); Contract.Assert(bindingType != null); IEnumerable<IEdmOperation> operations = model.SchemaElements.OfType<IEdmOperation>(); return operations.GetMatchedOperations(identifier, bindingType); }
private AuthorizedRolesAnnotation GetAuthorizedRolesAnnotation(IEdmType entityType) { IEdmCollectionType collection = entityType as IEdmCollectionType; IEdmType type = collection != null ? collection.ElementType.Definition : entityType as IEdmEntityType; Contract.Assert(type != null); return _model.GetAnnotationValue<AuthorizedRolesAnnotation>(type); }
/// <summary> /// Initializes a new instance of the <see cref="EdmEnumObject"/> class. /// </summary> /// <param name="edmType">The <see cref="IEdmEnumTypeReference"/> of this object.</param> /// <param name="value">The value of the enumeration type.</param> /// <param name="isNullable">true if this object can be nullable; otherwise, false.</param> public EdmEnumObject(IEdmEnumType edmType, string value, bool isNullable) { if (edmType == null) { throw Error.ArgumentNull("edmType"); } _edmType = edmType; Value = value; IsNullable = isNullable; }
public static IEnumerable<IEdmFunctionImport> FindFunctions(this IEdmEntityContainer container, string functionIdentifier, IEdmType bindingParameterType) { Contract.Assert(container != null); Contract.Assert(functionIdentifier != null); IEnumerable<IEdmOperationImport> procedures = container.OperationImports() .GetMatchingProcedures(functionIdentifier, bindingParameterType, isAction: false); return procedures.OfType<IEdmFunctionImport>(); }
/// <summary> /// Gets the EDM type for this segment. /// </summary> /// <param name="previousEdmType">The EDM type of the previous path segment.</param> /// <returns> /// The EDM type for this segment. /// </returns> public override IEdmType GetEdmType(IEdmType previousEdmType) { if (NavigationProperty != null) { return NavigationProperty.Partner.Multiplicity() == EdmMultiplicity.Many ? (IEdmType)NavigationProperty.ToEntityType().GetCollection() : (IEdmType)NavigationProperty.ToEntityType(); } return null; }
public static bool IsEquivalentTo(this IEdmType thisType, IEdmType otherType) { if (thisType != otherType) { if (thisType == null || otherType == null) { return false; } else { if (thisType.TypeKind == otherType.TypeKind) { EdmTypeKind typeKind = thisType.TypeKind; switch (typeKind) { case EdmTypeKind.None: { return otherType.TypeKind == EdmTypeKind.None; } case EdmTypeKind.Primitive: { return thisType.IsEquivalentTo((IEdmPrimitiveType)otherType); } case EdmTypeKind.Entity: case EdmTypeKind.Complex: case EdmTypeKind.Enum: { return thisType.IsEquivalentTo((IEdmSchemaType)otherType); } case EdmTypeKind.Row: { return thisType.IsEquivalentTo((IEdmRowType)otherType); } case EdmTypeKind.Collection: { return thisType.IsEquivalentTo((IEdmCollectionType)otherType); } case EdmTypeKind.EntityReference: { return thisType.IsEquivalentTo((IEdmEntityReferenceType)otherType); } } throw new InvalidOperationException(Strings.UnknownEnumVal_TypeKind(thisType.TypeKind)); } else { return false; } } } else { return true; } }
protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment) { try { return base.ParseAtEntityCollection(model, previous, previousEdmType, segment); } catch (ODataException) { return new KeyValuePathSegment(segment); } }
internal static void ValidateEntryInExpandedLink(IEdmEntityType entryEntityType, IEdmType parentNavigationPropertyType) { if (parentNavigationPropertyType != null) { IEdmEntityType baseType = (parentNavigationPropertyType.TypeKind == EdmTypeKind.Collection) ? ((IEdmEntityType) ((IEdmCollectionType) parentNavigationPropertyType).ElementType.Definition) : ((IEdmEntityType) parentNavigationPropertyType); if (!baseType.IsAssignableFrom(entryEntityType)) { throw new ODataException(Microsoft.Data.OData.Strings.WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType(entryEntityType.ODataFullName(), baseType.ODataFullName())); } } }
/// <summary> /// Constructor for ODataQueryOptionParser /// </summary> /// <param name="model">Model to use for metadata binding.</param> /// <param name="targetEdmType">The target EdmType to apply the query option on.</param> /// <param name="targetNavigationSource">The target navigation source to apply the query option on.</param> /// <param name="queryOptions">The dictionary storing query option key-value pairs.</param> public ODataQueryOptionParser(IEdmModel model, IEdmType targetEdmType, IEdmNavigationSource targetNavigationSource, IDictionary<string, string> queryOptions) { ExceptionUtils.CheckArgumentNotNull(queryOptions, "queryOptions"); this.targetEdmType = targetEdmType; this.targetNavigationSource = targetNavigationSource; this.queryOptions = queryOptions; this.Configuration = new ODataUriParserConfiguration(model) { ParameterAliasValueAccessor = new ParameterAliasValueAccessor(queryOptions.Where(_ => _.Key.StartsWith("@", StringComparison.Ordinal)).ToDictionary(_ => _.Key, _ => _.Value)) }; }
internal static bool TryCastCollectionAsType(this IEdmCollectionExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors) { if (!type.IsCollection()) { discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.CollectionExpressionNotValidForNonCollectionType, Edm.Strings.EdmModel_Validator_Semantic_CollectionExpressionNotValidForNonCollectionType) }; return(false); } IEdmTypeReference collectionElementType = type.AsCollection().ElementType(); bool success = true; List <EdmError> errors = new List <EdmError>(); IEnumerable <EdmError> recursiveErrors; foreach (IEdmExpression element in expression.Elements) { success = TryCast(element, collectionElementType, context, matchExactly, out recursiveErrors) && success; errors.AddRange(recursiveErrors); } discoveredErrors = errors; return(success); }
internal static bool TryCastRecordAsType(this IEdmRecordExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors) { EdmUtil.CheckArgumentNull(expression, "expression"); EdmUtil.CheckArgumentNull(type, "type"); if (!type.IsStructured()) { discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.RecordExpressionNotValidForNonStructuredType, Edm.Strings.EdmModel_Validator_Semantic_RecordExpressionNotValidForNonStructuredType) }; return(false); } HashSetInternal <string> foundProperties = new HashSetInternal <string>(); List <EdmError> errors = new List <EdmError>(); IEdmStructuredTypeReference structuredType = type.AsStructured(); foreach (IEdmProperty typeProperty in structuredType.StructuredDefinition().Properties()) { IEdmPropertyConstructor expressionProperty = expression.Properties.FirstOrDefault(p => p.Name == typeProperty.Name); if (expressionProperty == null) { errors.Add(new EdmError(expression.Location(), EdmErrorCode.RecordExpressionMissingRequiredProperty, Edm.Strings.EdmModel_Validator_Semantic_RecordExpressionMissingProperty(typeProperty.Name))); } else { IEnumerable <EdmError> recursiveErrors; if (!expressionProperty.Value.TryCast(typeProperty.Type, context, matchExactly, out recursiveErrors)) { foreach (EdmError error in recursiveErrors) { errors.Add(error); } } foundProperties.Add(typeProperty.Name); } } if (!structuredType.IsOpen()) { foreach (IEdmPropertyConstructor property in expression.Properties) { if (!foundProperties.Contains(property.Name)) { errors.Add(new EdmError(expression.Location(), EdmErrorCode.RecordExpressionHasExtraProperties, Edm.Strings.EdmModel_Validator_Semantic_RecordExpressionHasExtraProperties(property.Name))); } } } if (errors.FirstOrDefault() != null) { discoveredErrors = errors; return(false); } discoveredErrors = Enumerable.Empty <EdmError>(); return(true); }
public override IEdmType GetEdmType(IEdmType previousEdmType) { return(EdmCoreModel.Instance.FindDeclaredType("Edm.Int32")); }
/// <summary> /// Resolve bound operations based on name. /// </summary> /// <param name="model">The model to be used.</param> /// <param name="identifier">The operation name.</param> /// <param name="bindingType">The type operation was binding to.</param> /// <returns>Resolved operation list.</returns> public override IEnumerable <IEdmOperation> ResolveBoundOperations(IEdmModel model, string identifier, IEdmType bindingType) { if (identifier.Contains(".")) { return(base.ResolveBoundOperations(model, identifier, bindingType)); } return(model.SchemaElements.OfType <IEdmOperation>() .Where(operation => string.Equals( identifier, operation.Name, this.EnableCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) && operation.IsBound && operation.Parameters.Any() && operation.HasEquivalentBindingType(bindingType))); }
/// <summary> /// Try to resolve a function from the given inputs. /// </summary> /// <param name="identifier">The identifier of the function that we're trying to find</param> /// <param name="parameterNames">the names of the parameters to search for.</param> /// <param name="bindingType">the type of the previous segment</param> /// <param name="model">the model to use to look up the operation import</param> /// <param name="matchingOperation">The single matching function found.</param> /// <param name="resolver">Resolver to be used.</param> /// <returns>True if a function was matched, false otherwise. Will throw if the model has illegal operation imports.</returns> internal static bool ResolveOperationFromList(string identifier, IList <string> parameterNames, IEdmType bindingType, IEdmModel model, out IEdmOperation matchingOperation, ODataUriResolver resolver) { // TODO: update code that is duplicate between operation and operation import, add more tests. // If the previous segment is an open type, the service action name is required to be fully qualified or else we always treat it as an open property name. matchingOperation = null; if (bindingType != null) { // TODO: look up actual container names here? // When using extension, there may be function call with unqualified name. So loose the restriction here. if (bindingType.IsOpen() && !identifier.Contains(".") && resolver.GetType() == typeof(ODataUriResolver)) { return(false); } } IEnumerable <IEdmOperation> operationsFromModel; // The extension method FindBoundOperations & FindOperations call IEdmModel.FindDeclaredBoundOperations which can be implemented by anyone and it could throw any type of exception // so catching all of them and simply putting it in the inner exception. try { if (bindingType != null) { operationsFromModel = resolver.ResolveBoundOperations(model, identifier, bindingType); } else { operationsFromModel = resolver.ResolveUnboundOperations(model, identifier); } } catch (Exception exc) { if (ExceptionUtils.IsCatchableExceptionType(exc)) { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_FoundInvalidOperation(identifier), exc); } throw; } bool foundActionsWhenLookingForFunctions; // Filters candidates based on the parameter names specified in the uri, removes actions if there were parameters specified in the uri but set the out bool to indicate that. // If no parameters specified, then matches based on binding type or matches with operations with no parameters. IList <IEdmOperation> candidatesMatchingOperations = operationsFromModel.FilterOperationCandidatesBasedOnParameterList(bindingType, parameterNames, resolver.EnableCaseInsensitive, out foundActionsWhenLookingForFunctions); // Only filter if there is more than one and its needed. if (candidatesMatchingOperations.Count > 1) { candidatesMatchingOperations = candidatesMatchingOperations.FilterBoundOperationsWithSameTypeHierarchyToTypeClosestToBindingType(bindingType) as IList <IEdmOperation>; // This will be only null when no candidates are left. In that case, we can return false here. if (candidatesMatchingOperations == null) { if (foundActionsWhenLookingForFunctions) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier)); } return(false); } } // If any of the candidates are an action, it better be the only thing returned, and there can't be parameters in the URL if (ResolveActionFromCandidates(candidatesMatchingOperations, identifier, parameterNames.Count > 0, out matchingOperation)) { return(true); } if (foundActionsWhenLookingForFunctions) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier)); } // If more than one overload matches, try to select based on optional parameters if (candidatesMatchingOperations.Count > 1) { candidatesMatchingOperations = candidatesMatchingOperations.FilterOverloadsBasedOnParameterCount(parameterNames.Count); } if (candidatesMatchingOperations.Count > 1) { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_NoSingleMatchFound(identifier, string.Join(",", parameterNames.ToArray()))); } matchingOperation = candidatesMatchingOperations.Count > 0 ? candidatesMatchingOperations[0] : null; return(matchingOperation != null); }
public IEnumerable <IEdmOperation> FindDeclaredBoundOperations(IEdmType bindingType) { return(this.baseModel.FindDeclaredBoundOperations(bindingType)); }
public EdmTypeReferenceForTest(IEdmType definition, bool isNullable) : base(definition, isNullable) { }
/// <summary> /// Determine if the /// </summary> /// <param name="responseValue">The response value.</param> /// <param name="singleResultCollection">The content as SingleResult.Queryable.</param> /// <param name="actionDescriptor">The action context, i.e. action and controller name.</param> /// <param name="modelFunction">A function to get the model.</param> /// <param name="path">The OData path.</param> /// <returns></returns> private static bool ContainsAutoSelectExpandProperty( object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, Func <Type, IEdmModel> modelFunction, ODataPath path) { Type elementClrType = GetElementType(responseValue, singleResultCollection, actionDescriptor); IEdmModel model = modelFunction(elementClrType); if (model == null) { throw Error.InvalidOperation(SRResources.QueryGetModelMustNotReturnNull); } IEdmType type = null; IEdmModelClrTypeMappingHandler typeMappingHandler = model.GetAnnotationValue <IEdmModelClrTypeMappingHandler>(model); if (typeMappingHandler != null) { type = typeMappingHandler.MapClrInstanceToEdmType(model, responseValue); type = EdmLibHelpers.UnwrapCollectionType(type); } if (type == null) { type = model.GetEdmType(elementClrType); } IEdmEntityType baseEntityType = type as IEdmEntityType; IEdmStructuredType structuredType = type as IEdmStructuredType; IEdmProperty property = null; if (path != null) { string name; EdmLibHelpers.GetPropertyAndStructuredTypeFromPath(path.Segments, out property, out structuredType, out name); } if (baseEntityType != null) { List <IEdmEntityType> entityTypes = new List <IEdmEntityType>(); entityTypes.Add(baseEntityType); entityTypes.AddRange(EdmLibHelpers.GetAllDerivedEntityTypes(baseEntityType, model)); foreach (var entityType in entityTypes) { IEnumerable <IEdmNavigationProperty> navigationProperties = entityType == baseEntityType ? entityType.NavigationProperties() : entityType.DeclaredNavigationProperties(); if (navigationProperties != null) { if (navigationProperties.Any( navigationProperty => EdmLibHelpers.IsAutoExpand(navigationProperty, property, entityType, model))) { return(true); } } IEnumerable <IEdmStructuralProperty> properties = entityType == baseEntityType ? entityType.StructuralProperties() : entityType.DeclaredStructuralProperties(); if (properties != null) { foreach (var edmProperty in properties) { if (EdmLibHelpers.IsAutoSelect(edmProperty, property, entityType, model)) { return(true); } } } } } else if (structuredType != null) { IEnumerable <IEdmStructuralProperty> properties = structuredType.StructuralProperties(); if (properties != null) { foreach (var edmProperty in properties) { if (EdmLibHelpers.IsAutoSelect(edmProperty, property, structuredType, model)) { return(true); } } } } return(false); }
public CustomComplexTypeReference(IEdmType definition, bool isNullable) : base(definition, isNullable) { }
public static void SetClrType(this IEdmModel edmModel, IEdmType edmType, Type clrType) { edmModel.SetAnnotationValue(edmType, new OeValueAnnotation <Type>(clrType)); }
protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment) { try { return(base.ParseAtEntityCollection(model, previous, previousEdmType, segment)); } catch (ODataException) { return(new KeyValuePathSegment(segment)); } }
/// <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 || expectedPayloadKind == ODataPayloadKind.Delta) { 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())); } } }
/// <summary> /// Determines if the type of an expression is compatible with the provided type /// </summary> /// <param name="expression">The expression to assert the type of.</param> /// <param name="type">The type to assert the expression as.</param> /// <param name="context">The context paths are to be evaluated in.</param> /// <param name="matchExactly">A value indicating whether the expression must match the asserted type exactly, or simply be compatible.</param> /// <param name="discoveredErrors">Errors produced if the expression does not match the specified type.</param> /// <returns>A value indicating whether the expression is valid for the given type or not.</returns> /// <remarks>If the expression has an associated type, this function will check that it matches the expected type and stop looking further. /// If an expression claims a type, it must be validated that the type is valid for the expression. If the expression does not claim a type /// this method will attempt to check the validity of the expression itself with the asserted type.</remarks> public static bool TryCast(this IEdmExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors) { EdmUtil.CheckArgumentNull(expression, "expression"); type = type.AsActualTypeReference(); // If we don't have a type to assert this passes vacuously. if (type == null || type.TypeKind() == EdmTypeKind.None) { discoveredErrors = Enumerable.Empty <EdmError>(); return(true); } switch (expression.ExpressionKind) { case EdmExpressionKind.IntegerConstant: case EdmExpressionKind.StringConstant: case EdmExpressionKind.BinaryConstant: case EdmExpressionKind.BooleanConstant: case EdmExpressionKind.DateTimeOffsetConstant: case EdmExpressionKind.DecimalConstant: case EdmExpressionKind.FloatingConstant: case EdmExpressionKind.GuidConstant: case EdmExpressionKind.DurationConstant: case EdmExpressionKind.DateConstant: case EdmExpressionKind.TimeOfDayConstant: IEdmPrimitiveValue primitiveValue = (IEdmPrimitiveValue)expression; if (primitiveValue.Type != null) { return(TestTypeReferenceMatch(primitiveValue.Type, type, expression.Location(), matchExactly, out discoveredErrors)); } return(TryCastPrimitiveAsType(primitiveValue, type, out discoveredErrors)); case EdmExpressionKind.Null: return(TryCastNullAsType((IEdmNullExpression)expression, type, out discoveredErrors)); case EdmExpressionKind.Path: case EdmExpressionKind.PropertyPath: case EdmExpressionKind.NavigationPropertyPath: return(TryCastPathAsType((IEdmPathExpression)expression, type, context, matchExactly, out discoveredErrors)); case EdmExpressionKind.FunctionApplication: IEdmApplyExpression applyExpression = (IEdmApplyExpression)expression; if (applyExpression.AppliedFunction != null) { IEdmOperation operation = applyExpression.AppliedFunction as IEdmOperation; if (operation != null) { return(TestTypeReferenceMatch(operation.ReturnType, type, expression.Location(), matchExactly, out discoveredErrors)); } } // If we don't have the applied function we just assume that it will work. discoveredErrors = Enumerable.Empty <EdmError>(); return(true); case EdmExpressionKind.If: return(TryCastIfAsType((IEdmIfExpression)expression, type, context, matchExactly, out discoveredErrors)); case EdmExpressionKind.IsType: return(TestTypeReferenceMatch(EdmCoreModel.Instance.GetBoolean(false), type, expression.Location(), matchExactly, out discoveredErrors)); case EdmExpressionKind.Record: IEdmRecordExpression recordExpression = (IEdmRecordExpression)expression; if (recordExpression.DeclaredType != null) { return(TestTypeReferenceMatch(recordExpression.DeclaredType, type, expression.Location(), matchExactly, out discoveredErrors)); } return(TryCastRecordAsType(recordExpression, type, context, matchExactly, out discoveredErrors)); case EdmExpressionKind.Collection: IEdmCollectionExpression collectionExpression = (IEdmCollectionExpression)expression; if (collectionExpression.DeclaredType != null) { return(TestTypeReferenceMatch(collectionExpression.DeclaredType, type, expression.Location(), matchExactly, out discoveredErrors)); } return(TryCastCollectionAsType(collectionExpression, type, context, matchExactly, out discoveredErrors)); case EdmExpressionKind.Labeled: return(TryCast(((IEdmLabeledExpression)expression).Expression, type, context, matchExactly, out discoveredErrors)); case EdmExpressionKind.Cast: return(TestTypeReferenceMatch(((IEdmCastExpression)expression).Type, type, expression.Location(), matchExactly, out discoveredErrors)); case EdmExpressionKind.LabeledExpressionReference: return(TryCast(((IEdmLabeledExpressionReferenceExpression)expression).ReferencedLabeledExpression, type, out discoveredErrors)); case EdmExpressionKind.EnumMember: return(TryCastEnumConstantAsType((IEdmEnumMemberExpression)expression, type, matchExactly, out discoveredErrors)); default: discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionNotValidForTheAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionNotValidForTheAssertedType) }; return(false); } }
private static IEdmType GetEdmType(IEdmModel edmModel, Type clrType, bool testCollections) { Contract.Assert(edmModel != null); Contract.Assert(clrType != null); IEdmPrimitiveType primitiveType = clrType.GetEdmPrimitiveType(); if (primitiveType != null) { return(primitiveType); } else { if (testCollections) { Type enumerableOfT = ExtractGenericInterface(clrType, typeof(IEnumerable <>)); if (enumerableOfT != null) { Type elementClrType = enumerableOfT.GetGenericArguments()[0]; // IEnumerable<SelectExpandWrapper<T>> is a collection of T. Type entityType; if (IsSelectExpandWrapper(elementClrType, out entityType)) { elementClrType = entityType; } if (IsComputeWrapper(elementClrType, out entityType)) { elementClrType = entityType; } IEdmType elementType = GetEdmType(edmModel, elementClrType, testCollections: false); if (elementType != null) { return(new EdmCollectionType(elementType.ToEdmTypeReference(IsNullable(elementClrType)))); } } } Type underlyingType = TypeHelper.GetUnderlyingTypeOrSelf(clrType); if (TypeHelper.IsEnum(underlyingType)) { clrType = underlyingType; } // search for the ClrTypeAnnotation and return it if present IEdmType returnType = edmModel .SchemaElements .OfType <IEdmType>() .Select(edmType => new { EdmType = edmType, Annotation = edmModel.GetAnnotationValue <ClrTypeAnnotation>(edmType) }) .Where(tuple => tuple.Annotation != null && tuple.Annotation.ClrType == clrType) .Select(tuple => tuple.EdmType) .SingleOrDefault(); // default to the EdmType with the same name as the ClrType name returnType = returnType ?? edmModel.FindType(clrType.EdmFullName()); if (clrType.BaseType != null) { // go up the inheritance tree to see if we have a mapping defined for the base type. returnType = returnType ?? GetEdmType(edmModel, clrType.BaseType, testCollections); } return(returnType); } }
private static bool IsAssignableFrom(IEdmType candidateSupertype, IEdmType candidateSubtype) { return(candidateSubtype.IsOrInheritsFrom(candidateSupertype)); }
/// <summary> /// /// </summary> /// <param name="context"></param> public virtual bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } ActionModel action = context.Action; if (context.EntitySet == null && context.Singleton == null) { return(false); } IEdmNavigationSource navigationSource = context.EntitySet == null ? (IEdmNavigationSource)context.Singleton : (IEdmNavigationSource)context.EntitySet; IEdmModel model = context.Model; string prefix = context.Prefix; IEdmEntityType entityType = navigationSource.EntityType(); bool hasKeyParameter = HasKeyParameter(entityType, action); // found int keyNumber = entityType.Key().Count(); IEdmType bindType = entityType; if (!hasKeyParameter) { // bond to collection bindType = new EdmCollectionType(new EdmEntityTypeReference(entityType, true)); keyNumber = 0; } string actionName = action.ActionMethod.Name; var operations = model.FindBoundOperations(bindType).Where(p => p.Name == actionName); var actions = operations.OfType <IEdmAction>().ToList(); if (actions.Count == 1) // action overload on binding type, only one action overload on the same binding type { if (action.Parameters.Any(p => p.ParameterType == typeof(ODataActionParameters))) { // we find a action route IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>(); if (context.EntitySet != null) { segments.Add(new EntitySetSegmentTemplate(context.EntitySet)); } else { segments.Add(new SingletonSegmentTemplate(context.Singleton)); } if (hasKeyParameter) { segments.Add(new KeySegmentTemplate(entityType)); } segments.Add(new ActionSegmentTemplate(actions[0], false)); ODataPathTemplate template = new ODataPathTemplate(segments); action.AddSelector(prefix, model, template); return(true); } } var functions = operations.OfType <IEdmFunction>().ToList(); IEdmFunction function = FindMatchFunction(keyNumber, functions, action); if (function != null) { IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>(); if (context.EntitySet != null) { segments.Add(new EntitySetSegmentTemplate(context.EntitySet)); } else { segments.Add(new SingletonSegmentTemplate(context.Singleton)); } if (hasKeyParameter) { segments.Add(new KeySegmentTemplate(entityType)); } segments.Add(new FunctionSegmentTemplate(function, false)); ODataPathTemplate template = new ODataPathTemplate(segments); action.AddSelector(prefix, model, template); return(true); } // in OData operationImport routing convention, all action are processed by default // even it's not a really edm operation import call. return(false); }
public virtual IEnumerable <IEdmOperation> FindDeclaredBoundOperations(string qualifiedName, IEdmType bindingType) { return(this.FindDeclaredOperations(qualifiedName).Where(o => o.IsBound && o.Parameters.Any() && o.HasEquivalentBindingType(bindingType))); }
/// <summary> /// Constructor for ODataQueryOptionParser /// </summary> /// <param name="model">Model to use for metadata binding.</param> /// <param name="targetEdmType">The target EdmType to apply the query option on.</param> /// <param name="targetNavigationSource">The target navigation source to apply the query option on.</param> /// <param name="queryOptions">The dictionary storing query option key-value pairs.</param> public ODataQueryOptionParser(IEdmModel model, IEdmType targetEdmType, IEdmNavigationSource targetNavigationSource, IDictionary <string, string> queryOptions) : this(model, targetEdmType, targetNavigationSource, queryOptions, null) { }
public static Type GetClrType(IEdmType edmType, IEdmModel edmModel) { return(GetClrType(edmType, edmModel, _defaultAssemblyResolver)); }
/// <summary> /// Returns the corresponding edm type reference for the given edm type. /// </summary> /// <param name="edmType">EdmType instance.</param> /// <param name="isNullable">A boolean value indicating whether the clr type of this edm type is nullable</param> /// <returns>Returns the corresponding edm type reference for the given edm type.</returns> internal static IEdmTypeReference ToEdmTypeReference(this IEdmType edmType, bool isNullable) { return(EdmLibraryExtensions.ToTypeReference(edmType, isNullable)); }
/// <summary> /// Gets the single instance of <see cref="ClientTypeAnnotation"/> from the given instance of <paramref name="edmType"/>. /// </summary> /// <param name="model">The model the <paramref name="edmType"/> belongs to.</param> /// <param name="edmType">IEdmType instance to get the annotation.</param> /// <returns>Returns the single instance of <see cref="ClientTypeAnnotation"/> from the given instance of <paramref name="edmType"/>.</returns> internal static ClientTypeAnnotation GetClientTypeAnnotation(this IEdmModel model, IEdmType edmType) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmType != null, "edmType != null"); return(model.GetAnnotationValue <ClientTypeAnnotation>(edmType)); }
internal static bool TryCastIfAsType(this IEdmIfExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors) { IEnumerable <EdmError> ifTrueErrors; IEnumerable <EdmError> ifFalseErrors; bool success = TryCast(expression.TrueExpression, type, context, matchExactly, out ifTrueErrors); success = TryCast(expression.FalseExpression, type, context, matchExactly, out ifFalseErrors) && success; if (!success) { List <EdmError> errorList = new List <EdmError>(ifTrueErrors); errorList.AddRange(ifFalseErrors); discoveredErrors = errorList; } else { discoveredErrors = Enumerable.Empty <EdmError>(); } return(success); }
/// <summary> /// Gets the corresponding CLR type for a given Edm type reference. /// </summary> /// <param name="edmModel">The Edm model.</param> /// <param name="edmType">The Edm type.</param> /// <returns>Null or the CLR type.</returns> internal static Type GetClrType(this IEdmModel edmModel, IEdmType edmType) { return(edmModel.GetClrType(edmType, AssemblyResolverHelper.Default)); }
internal static bool ResolveOperationFromList(string identifier, IEnumerable <string> parameterNames, IEdmType bindingType, IEdmModel model, out IEdmOperation matchingOperation, ODataUriResolver resolver) { // TODO: update code that is duplicate between operation and operation import, add more tests. // If the previous segment is an open type, the service action name is required to be fully qualified or else we always treat it as an open property name. if (bindingType != null) { // TODO: look up actual container names here? // When using extension, there may be function call with unqualified name. So loose the restriction here. if (bindingType.IsOpenType() && !identifier.Contains(".") && resolver.GetType() == typeof(ODataUriResolver)) { matchingOperation = null; return(false); } } IList <IEdmOperation> candidateMatchingOperations = null; // The extension method FindBoundOperations & FindOperations call IEdmModel.FindDeclaredBoundOperations which can be implemented by anyone and it could throw any type of exception // so catching all of them and simply putting it in the inner exception. try { if (bindingType != null) { candidateMatchingOperations = resolver.ResolveBoundOperations(model, identifier, bindingType).ToList(); } else { candidateMatchingOperations = resolver.ResolveUnboundOperations(model, identifier).ToList(); } } catch (Exception exc) { if (ExceptionUtils.IsCatchableExceptionType(exc)) { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_FoundInvalidOperation(identifier), exc); } throw; } IList <IEdmAction> foundActionsWhenLookingForFunctions = new List <IEdmAction>(); int parameterNamesCount = parameterNames.Count(); if (bindingType != null) { candidateMatchingOperations = candidateMatchingOperations.EnsureOperationsBoundWithBindingParameter().ToList(); } // If the number of parameters > 0 then this has to be a function as actions can't have parameters on the uri only in the payload. Filter further by parameters in this case, otherwise don't. if (parameterNamesCount > 0) { // can only be a function as only functions have parameters on the uri. candidateMatchingOperations = candidateMatchingOperations.RemoveActions(out foundActionsWhenLookingForFunctions).FilterFunctionsByParameterNames(parameterNames, resolver.EnableCaseInsensitive).Cast <IEdmOperation>().ToList(); } else if (bindingType != null) { // Filter out functions with more than one parameter. Actions should not be filtered as the parameters are in the payload not the uri candidateMatchingOperations = candidateMatchingOperations.Where(o => (o.IsFunction() && o.Parameters.Count() == 1) || o.IsAction()).ToList(); } else { // Filter out functions with any parameters candidateMatchingOperations = candidateMatchingOperations.Where(o => (o.IsFunction() && !o.Parameters.Any()) || o.IsAction()).ToList(); } // Only filter if there is more than one and its needed. if (candidateMatchingOperations.Count > 1) { candidateMatchingOperations = candidateMatchingOperations.FilterBoundOperationsWithSameTypeHierarchyToTypeClosestToBindingType(bindingType).ToList(); } // If any of the things returned are an action, it better be the only thing returned, and there can't be parameters in the URL if (candidateMatchingOperations.Any(f => f.IsAction())) { if (candidateMatchingOperations.Count > 1) { if (candidateMatchingOperations.Any(o => o.IsFunction())) { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleOperationOverloads(identifier)); } else { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleActionOverloads(identifier)); } } if (parameterNames.Count() != 0) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier)); } matchingOperation = candidateMatchingOperations.Single(); return(true); } if (foundActionsWhenLookingForFunctions.Count > 0) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier)); } if (candidateMatchingOperations.Count > 1) { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_NoSingleMatchFound(identifier, string.Join(",", parameterNames.ToArray()))); } matchingOperation = candidateMatchingOperations.SingleOrDefault(); return(matchingOperation != null); }
private IEdmValue Eval(IEdmExpression expression, IEdmStructuredValue context) { switch (expression.ExpressionKind) { case EdmExpressionKind.IntegerConstant: return((IEdmIntegerConstantExpression)expression); case EdmExpressionKind.StringConstant: return((IEdmStringConstantExpression)expression); case EdmExpressionKind.BinaryConstant: return((IEdmBinaryConstantExpression)expression); case EdmExpressionKind.BooleanConstant: return((IEdmBooleanConstantExpression)expression); case EdmExpressionKind.DateTimeOffsetConstant: return((IEdmDateTimeOffsetConstantExpression)expression); case EdmExpressionKind.DecimalConstant: return((IEdmDecimalConstantExpression)expression); case EdmExpressionKind.FloatingConstant: return((IEdmFloatingConstantExpression)expression); case EdmExpressionKind.GuidConstant: return((IEdmGuidConstantExpression)expression); case EdmExpressionKind.DurationConstant: return((IEdmDurationConstantExpression)expression); case EdmExpressionKind.DateConstant: return((IEdmDateConstantExpression)expression); case EdmExpressionKind.TimeOfDayConstant: return((IEdmTimeOfDayConstantExpression)expression); case EdmExpressionKind.Null: return((IEdmNullExpression)expression); case EdmExpressionKind.Path: case EdmExpressionKind.AnnotationPath: { if (context == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_NoContextPath); } IEdmPathExpression pathExpression = (IEdmPathExpression)expression; IEdmValue result = context; #if ORCAS // [EdmLib] Need to handle paths that bind to things other than properties. foreach (string hop in pathExpression.PathSegments) { result = FindProperty(hop, result); if (result == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundPath(hop)); } } #else // Only Support Annotation in EntityType or ComplexType or Property or NavigationProperty. // Empty Path is not supported. foreach (string hop in pathExpression.PathSegments) { if (hop.Contains("@")) { var currentPathSegmentInfos = hop.Split('@'); var propertyName = currentPathSegmentInfos[0]; var termInfo = currentPathSegmentInfos[1]; IEdmExpression termCastExpression = null; if (!string.IsNullOrWhiteSpace(termInfo)) { var termInfos = termInfo.Split('#'); if (termInfos.Length <= 2) { string termName = termInfos[0]; string qualifier = termInfos.Length == 2 ? termInfos[1] : null; if (string.IsNullOrWhiteSpace(propertyName) && this.getAnnotationExpressionForType != null) { termCastExpression = this.getAnnotationExpressionForType(this.edmModel, context.Type.Definition, termName, qualifier); } else if (!string.IsNullOrWhiteSpace(propertyName) && this.getAnnotationExpressionForProperty != null) { termCastExpression = this.getAnnotationExpressionForProperty(this.edmModel, context.Type.Definition, propertyName, termName, qualifier); } } } if (termCastExpression == null) { result = null; break; } result = this.Eval(termCastExpression, context); } else if (hop == "$count") { var edmCollectionValue = result as IEdmCollectionValue; if (edmCollectionValue != null) { result = new EdmIntegerConstant(edmCollectionValue.Elements.Count()); } else { result = null; break; } } else if (hop.Contains(".")) { if (this.edmModel == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_TypeCastNeedsEdmModel); } IEdmType typeSegmentClientType = this.resolveTypeFromName(hop, this.edmModel); if (typeSegmentClientType == null) { result = null; break; } IEdmTypeReference operandType = result.Type; EdmValueKind operandKind = result.ValueKind; if (operandKind == EdmValueKind.Collection) { List <IEdmDelayedValue> elementValues = new List <IEdmDelayedValue>(); var collection = result as IEdmCollectionValue; foreach (IEdmDelayedValue element in collection.Elements) { if (element.Value.Type.Definition.IsOrInheritsFrom(typeSegmentClientType)) { elementValues.Add(element); } } result = new EdmCollectionValue( new EdmCollectionTypeReference(new EdmCollectionType(typeSegmentClientType.GetTypeReference(false))), elementValues); } else if (operandKind != EdmValueKind.Structured || (operandKind == EdmValueKind.Structured && !operandType.Definition.IsOrInheritsFrom(typeSegmentClientType))) { result = null; break; } } else { result = FindProperty(hop, result); if (result == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundPath(hop)); } } } #endif return(result); } case EdmExpressionKind.PropertyPath: case EdmExpressionKind.NavigationPropertyPath: { EdmUtil.CheckArgumentNull(context, "context"); IEdmPathExpression pathExpression = (IEdmPathExpression)expression; IEdmValue result = context; // [EdmLib] Need to handle paths that bind to things other than properties. foreach (string hop in pathExpression.PathSegments) { result = FindProperty(hop, result); if (result == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundPath(hop)); } } return(result); } case EdmExpressionKind.FunctionApplication: { IEdmApplyExpression apply = (IEdmApplyExpression)expression; IEdmFunction target = apply.AppliedFunction; if (target != null) { IList <IEdmExpression> argumentExpressions = apply.Arguments.ToList(); IEdmValue[] arguments = new IEdmValue[argumentExpressions.Count]; { int argumentIndex = 0; foreach (IEdmExpression argument in argumentExpressions) { arguments[argumentIndex++] = this.Eval(argument, context); } } //// Static validation will have checked that the number and types of arguments are correct, //// so those checks are not performed dynamically. Func <IEdmValue[], IEdmValue> operationEvaluator; if (this.builtInFunctions.TryGetValue(target, out operationEvaluator)) { return(operationEvaluator(arguments)); } if (this.lastChanceOperationApplier != null) { return(this.lastChanceOperationApplier(target.FullName(), arguments)); } } throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundFunction(target != null ? target.ToTraceString() : string.Empty)); } case EdmExpressionKind.If: { IEdmIfExpression ifExpression = (IEdmIfExpression)expression; if (((IEdmBooleanValue)this.Eval(ifExpression.TestExpression, context)).Value) { return(this.Eval(ifExpression.TrueExpression, context)); } return(this.Eval(ifExpression.FalseExpression, context)); } case EdmExpressionKind.IsType: { IEdmIsTypeExpression isType = (IEdmIsTypeExpression)expression; IEdmValue operand = this.Eval(isType.Operand, context); IEdmTypeReference targetType = isType.Type; return(new EdmBooleanConstant(MatchesType(targetType, operand))); } case EdmExpressionKind.Cast: { IEdmCastExpression castType = (IEdmCastExpression)expression; IEdmValue operand = this.Eval(castType.Operand, context); IEdmTypeReference targetType = castType.Type; return(Cast(targetType, operand)); } case EdmExpressionKind.Record: { IEdmRecordExpression record = (IEdmRecordExpression)expression; DelayedExpressionContext recordContext = new DelayedExpressionContext(this, context); List <IEdmPropertyValue> propertyValues = new List <IEdmPropertyValue>(); //// Static validation will have checked that the set of supplied properties are appropriate //// for the supplied type and have no duplicates, so those checks are not performed dynamically. foreach (IEdmPropertyConstructor propertyConstructor in record.Properties) { propertyValues.Add(new DelayedRecordProperty(recordContext, propertyConstructor)); } EdmStructuredValue result = new EdmStructuredValue(record.DeclaredType != null ? record.DeclaredType.AsStructured() : null, propertyValues); return(result); } case EdmExpressionKind.Collection: { IEdmCollectionExpression collection = (IEdmCollectionExpression)expression; DelayedExpressionContext collectionContext = new DelayedExpressionContext(this, context); List <IEdmDelayedValue> elementValues = new List <IEdmDelayedValue>(); //// Static validation will have checked that the result types of the element expressions are //// appropriate and so these checks are not performed dynamically. foreach (IEdmExpression element in collection.Elements) { elementValues.Add(this.MapLabeledExpressionToDelayedValue(element, collectionContext, context)); } EdmCollectionValue result = new EdmCollectionValue(collection.DeclaredType != null ? collection.DeclaredType.AsCollection() : null, elementValues); return(result); } case EdmExpressionKind.LabeledExpressionReference: { return(this.MapLabeledExpressionToDelayedValue(((IEdmLabeledExpressionReferenceExpression)expression).ReferencedLabeledExpression, null, context).Value); } case EdmExpressionKind.Labeled: return(this.MapLabeledExpressionToDelayedValue(expression, new DelayedExpressionContext(this, context), context).Value); case EdmExpressionKind.EnumMember: IEdmEnumMemberExpression enumMemberExpression = (IEdmEnumMemberExpression)expression; var enumMembers = enumMemberExpression.EnumMembers.ToList(); IEdmEnumType enumType = enumMembers.First().DeclaringType; IEdmEnumTypeReference enumTypeReference = new EdmEnumTypeReference(enumType, false); if (enumMembers.Count == 1) { return(new EdmEnumValue(enumTypeReference, enumMemberExpression.EnumMembers.Single())); } else { if (!enumType.IsFlags || !EdmEnumValueParser.IsEnumIntegerType(enumType)) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Type {0} cannot be assigned with multi-values.", enumType.FullName())); } long result = 0; foreach (var enumMember in enumMembers) { long value = enumMember.Value.Value; result |= value; } return(new EdmEnumValue(enumTypeReference, new EdmEnumMemberValue(result))); } default: throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnrecognizedExpressionKind(((int)expression.ExpressionKind).ToString(System.Globalization.CultureInfo.InvariantCulture))); } }
internal static bool TryCastPathAsType(this IEdmPathExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors) { IEdmStructuredType structuredContext = context as IEdmStructuredType; if (structuredContext != null) { IEdmType result = context; // [EdmLib] Need to handle paths that bind to things other than properties. foreach (string segment in expression.PathSegments) { IEdmStructuredType structuredResult = result as IEdmStructuredType; if (structuredResult == null) { discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.PathIsNotValidForTheGivenContext, Edm.Strings.EdmModel_Validator_Semantic_PathIsNotValidForTheGivenContext(segment)) }; return(false); } IEdmProperty resultProperty = structuredResult.FindProperty(segment); result = (resultProperty != null) ? resultProperty.Type.Definition : null; // If the path is not resolved, it could refer to an open type, and we cannot make an assertion about its type. if (result == null) { discoveredErrors = Enumerable.Empty <EdmError>(); return(true); } } return(TestTypeMatch(result, type.Definition, expression.Location(), matchExactly, out discoveredErrors)); } discoveredErrors = Enumerable.Empty <EdmError>(); return(true); }
public CustomEntityTypeReference(IEdmType definition, bool isNullable) : base(definition, isNullable) { }
/// <inheritdoc/> public override IEnumerable <IEdmOperation> ResolveBoundOperations(IEdmModel model, string identifier, IEdmType bindingType) { return(_unqualified.ResolveBoundOperations(model, identifier, bindingType)); }
/// <summary> /// Gets the EDM type for this segment. /// </summary> /// <param name="previousEdmType">The EDM type of the previous path segment.</param> /// <returns> /// The EDM type for this segment. /// </returns> public override IEdmType GetEdmType(IEdmType previousEdmType) { return(null); }
public CustomEntityReferenceTypeReference(IEdmType type, bool isNullable) : base(type, isNullable) { }