コード例 #1
0
        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));
        }
コード例 #2
0
ファイル: ClientTypeUtil.cs プロジェクト: AlineGuan/odata.net
 /// <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);
 }
コード例 #3
0
ファイル: ClientTypeUtil.cs プロジェクト: AlineGuan/odata.net
        /// <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);
        }
コード例 #4
0
ファイル: EpmSourceTree.cs プロジェクト: nickchal/pash
 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;
 }
コード例 #5
0
 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);
 }
コード例 #6
0
ファイル: Resolvers.cs プロジェクト: nickgoodrow/ODataSamples
 public override IEnumerable<IEdmOperation> ResolveBoundOperations(
     IEdmModel model,
     string identifier,
     IEdmType bindingType)
 {
     return unqualified.ResolveBoundOperations(model, identifier, bindingType);
 }
コード例 #7
0
ファイル: ExceptionUtil.cs プロジェクト: larsenjo/odata.net
 /// <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));
     }
 }
コード例 #8
0
        /// <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;
        }
コード例 #9
0
ファイル: EdmAssertions.cs プロジェクト: cxlove/odata.net
 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);
 }
コード例 #10
0
ファイル: AvroWriter.cs プロジェクト: AlineGuan/odata.net
        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;
        }
コード例 #11
0
 private static IEdmTypeReference GetNullablePayloadTypeReference(IEdmType payloadType)
 {
     if (payloadType != null)
     {
         return payloadType.ToTypeReference(true);
     }
     return null;
 }
コード例 #12
0
 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");
 }
コード例 #13
0
ファイル: ClientTypeAnnotation.cs プロジェクト: nickchal/pash
 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);
 }
コード例 #14
0
ファイル: DSPResource.cs プロジェクト: AlineGuan/odata.net
 /// <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);
     }
 }
コード例 #15
0
 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);
 }
コード例 #16
0
 /// <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;
 }
コード例 #17
0
 /// <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;
 }
コード例 #18
0
 /// <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;
 }
コード例 #19
0
        /// <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;
        }
コード例 #20
0
 /// <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));
     }
 }
コード例 #21
0
        /// <inheritdoc/>
        public override IEdmType GetEdmType(IEdmType previousEdmType)
        {
            if (Singleton != null)
            {
                return Singleton.EntityType();
            }

            return null;
        }
コード例 #22
0
        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);
        }
コード例 #23
0
        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);
        }
コード例 #24
0
ファイル: EdmEnumObject.cs プロジェクト: ZhaoYngTest01/WebApi
 /// <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;
 }
コード例 #25
0
        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>();
        }
コード例 #26
0
 /// <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;
 }
コード例 #27
0
ファイル: EdmElementComparer.cs プロジェクト: nickchal/pash
		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;
			}
		}
コード例 #28
0
 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);
     }
 }
コード例 #29
0
 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()));
         }
     }
 }
コード例 #30
0
        /// <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))
            };
        }
コード例 #31
0
        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);
        }
コード例 #32
0
        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);
        }
コード例 #33
0
 public override IEdmType GetEdmType(IEdmType previousEdmType)
 {
     return(EdmCoreModel.Instance.FindDeclaredType("Edm.Int32"));
 }
コード例 #34
0
        /// <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)));
        }
コード例 #35
0
        /// <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);
        }
コード例 #36
0
 public IEnumerable <IEdmOperation> FindDeclaredBoundOperations(IEdmType bindingType)
 {
     return(this.baseModel.FindDeclaredBoundOperations(bindingType));
 }
コード例 #37
0
ファイル: UtilsTests.cs プロジェクト: zdzislaw/odata.net
 public EdmTypeReferenceForTest(IEdmType definition, bool isNullable)
     : base(definition, isNullable)
 {
 }
コード例 #38
0
        /// <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);
        }
コード例 #39
0
 public CustomComplexTypeReference(IEdmType definition, bool isNullable)
     : base(definition, isNullable)
 {
 }
コード例 #40
0
 public static void SetClrType(this IEdmModel edmModel, IEdmType edmType, Type clrType)
 {
     edmModel.SetAnnotationValue(edmType, new OeValueAnnotation <Type>(clrType));
 }
コード例 #41
0
 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));
     }
 }
コード例 #42
0
        /// <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()));
                }
            }
        }
コード例 #43
0
        /// <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);
            }
        }
コード例 #44
0
        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);
            }
        }
コード例 #45
0
ファイル: MetadataUtil.cs プロジェクト: zdzislaw/odata.net
 private static bool IsAssignableFrom(IEdmType candidateSupertype, IEdmType candidateSubtype)
 {
     return(candidateSubtype.IsOrInheritsFrom(candidateSupertype));
 }
コード例 #46
0
        /// <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);
        }
コード例 #47
0
 public virtual IEnumerable <IEdmOperation> FindDeclaredBoundOperations(string qualifiedName, IEdmType bindingType)
 {
     return(this.FindDeclaredOperations(qualifiedName).Where(o => o.IsBound && o.Parameters.Any() && o.HasEquivalentBindingType(bindingType)));
 }
コード例 #48
0
 /// <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)
 {
 }
コード例 #49
0
 public static Type GetClrType(IEdmType edmType, IEdmModel edmModel)
 {
     return(GetClrType(edmType, edmModel, _defaultAssemblyResolver));
 }
コード例 #50
0
 /// <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));
 }
コード例 #51
0
        /// <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));
        }
コード例 #52
0
        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);
        }
コード例 #53
0
 /// <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));
 }
コード例 #54
0
        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);
        }
コード例 #55
0
        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)));
            }
        }
コード例 #56
0
        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);
        }
コード例 #57
0
 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));
 }
コード例 #59
0
ファイル: BatchPathSegment.cs プロジェクト: tvdburgt/WebApi
 /// <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);
 }
コード例 #60
0
 public CustomEntityReferenceTypeReference(IEdmType type, bool isNullable)
     : base(type, isNullable)
 {
 }