コード例 #1
0
 protected CsdlSemanticsOperationImport(CsdlSemanticsEntityContainer container, CsdlOperationImport operationImport, IEdmOperation operation)
     : base(operationImport)
 {
     this.container = container;
     this.operationImport = operationImport;
     this.Operation = operation;
 }
コード例 #2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="jsonLightOutputContext">The output context to write to.</param>
        /// <param name="operation">The operation import whose parameters will be written.</param>
        internal ODataJsonLightParameterWriter(ODataJsonLightOutputContext jsonLightOutputContext, IEdmOperation operation)
            : base(jsonLightOutputContext, operation)
        {
            Debug.Assert(jsonLightOutputContext != null, "jsonLightOutputContext != null");

            this.jsonLightOutputContext = jsonLightOutputContext;
            this.jsonLightValueSerializer = new ODataJsonLightValueSerializer(this.jsonLightOutputContext);
        }
コード例 #3
0
        public ODataAvroParameterReader(ODataAvroInputContext inputContext, IEdmOperation operation)
        {
            Debug.Assert(inputContext != null, "inputContext != null");
            Debug.Assert(operation != null, "operation != null");

            this.inputContext = inputContext;
            this.operation = operation;
            this.state = ODataParameterReaderState.Start;
        }
コード例 #4
0
        public ODataAvroParameterWriter(ODataAvroOutputContext outputContext, IEdmOperation operation)
        {
            Debug.Assert(outputContext != null, "outputContext != null");
            Debug.Assert(operation != null, "operation != null");

            this.outputContext = outputContext;
            schema = (RecordSchema)this.outputContext.AvroWriter.UpdateSchema(null, this.GetTmpType(operation));
            this.record = new AvroRecord(schema);
        }
コード例 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EdmOperationParameter"/> class.
        /// </summary>
        /// <param name="declaringOperation">Declaring function of the parameter.</param>
        /// <param name="name">Name of the parameter.</param>
        /// <param name="type">Type of the parameter.</param>
        public EdmOperationParameter(IEdmOperation declaringOperation, string name, IEdmTypeReference type)
            : base(name)
        {
            EdmUtil.CheckArgumentNull(declaringOperation, "declaringFunction");
            EdmUtil.CheckArgumentNull(name, "name");
            EdmUtil.CheckArgumentNull(type, "type");

            this.Type = type;
            this.DeclaringOperation = declaringOperation;
        }
コード例 #6
0
        public static bool IsDuplicateOperation(IEdmOperation operation, IEnumerable<IEdmOperation> candidateDuplicateOperations)
        {
            var validator = new DuplicateOperationValidator(null);
            foreach (var candidateOperation in candidateDuplicateOperations)
            {
                validator.ValidateNotDuplicate(candidateOperation, true /*skipError*/);
            }

            return validator.ValidateNotDuplicate(operation, true /*skipError*/);
        }
コード例 #7
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="jsonLightInputContext">The input to read the payload from.</param>
        /// <param name="operation">The operation import whose parameters are being read.</param>
        internal ODataJsonLightParameterReader(ODataJsonLightInputContext jsonLightInputContext, IEdmOperation operation)
            : base(jsonLightInputContext, operation)
        {
            Debug.Assert(jsonLightInputContext != null, "jsonLightInputContext != null");
            Debug.Assert(jsonLightInputContext.ReadingResponse == false, "jsonLightInputContext.ReadingResponse == false");
            Debug.Assert(operation != null, "operationImport != null");

            this.jsonLightInputContext = jsonLightInputContext;
            this.jsonLightParameterDeserializer = new ODataJsonLightParameterDeserializer(this, jsonLightInputContext);
            Debug.Assert(this.jsonLightInputContext.Model.IsUserModel(), "this.jsonLightInputContext.Model.IsUserModel()");
        }
コード例 #8
0
        private IEdmType GetTmpType(IEdmOperation operation)
        {
            EdmComplexType type = new EdmComplexType(operation.Namespace, operation.Name + AvroConstants.ParameterTypeSuffix);

            foreach (var parameter in operation.Parameters.Skip(operation.IsBound ? 1 : 0))
            {
                type.AddStructuralProperty(parameter.Name, parameter.Type);
            }

            return type;
        }
コード例 #9
0
        /// <summary>
        /// Initializes a new instance of <see cref="EdmOperationImport"/> class.
        /// </summary>
        /// <param name="container">An <see cref="IEdmEntityContainer"/> containing this operation import.</param>
        /// <param name="operation">The operation of the import.</param>
        /// <param name="name">Name of the operation import.</param>
        /// <param name="entitySet">An entity set containing entities returned by this operation import. 
        /// The two expression kinds supported are <see cref="IEdmEntitySetReferenceExpression"/> and <see cref="IEdmPathExpression"/>.</param>
        protected EdmOperationImport(
            IEdmEntityContainer container,
            IEdmOperation operation,
            string name,
            IEdmExpression entitySet)
            : base(name)
        {
            EdmUtil.CheckArgumentNull(container, "container");
            EdmUtil.CheckArgumentNull(operation, this.OperationArgumentNullParameterName());

            this.Container = container;
            this.Operation = operation;
            this.EntitySet = entitySet;
        }
コード例 #10
0
        public override IDictionary<IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary<string, SingleValueNode> input)
        {
            Dictionary<IEdmOperationParameter, SingleValueNode> result = new Dictionary<IEdmOperationParameter, SingleValueNode>(EqualityComparer<IEdmOperationParameter>.Default);
            foreach (var item in input)
            {
                IEdmOperationParameter functionParameter = null;
                if (EnableCaseInsensitive)
                {
                    functionParameter = ODataUriResolver.ResolveOpearationParameterNameCaseInsensitive(operation, item.Key);
                }
                else
                {
                    functionParameter = operation.FindParameter(item.Key);
                }

                // ensure parameter name existis
                if (functionParameter == null)
                {
                    throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name));
                }

                SingleValueNode newVal = item.Value;

                if (functionParameter.Type.IsEnum()
                    && newVal is ConstantNode
                    && newVal.TypeReference != null
                    && newVal.TypeReference.IsString())
                {
                    string text = ((ConstantNode)item.Value).Value as string;
                    ODataEnumValue val;
                    IEdmTypeReference typeRef = functionParameter.Type;

                    if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val))
                    {
                        newVal = new ConstantNode(val, text, typeRef);
                    }
                }

                result.Add(functionParameter, newVal);
            }

            return result;
        }
コード例 #11
0
        /// <summary
        /// Compares Action and Function elements from CSDL to IEdmComplexTypes in the model.
        /// </summary>
        /// <param name="schemaElements">The CSDL schema elements to extract ComplexType elements from.</param>
        /// <param name="model">The Edm model to extract the IEdmComplexTypes from.</param>
        private static void CompareActionsAndFunctions(IEnumerable <XElement> schemaElements, IEdmModel model)
        {
            foreach (var schemaElement in schemaElements)
            {
                var namespaceName     = schemaElement.GetAttributeValue("Namespace");
                var operationElements = schemaElement.EdmElements("Action").Concat(schemaElement.EdmElements("Function"));

                foreach (var operationElement in operationElements)
                {
                    // Find matching operation from model, matching and validating
                    // parameters at the same time.
                    var parameterElements = operationElement.EdmElements("Parameter").ToList();
                    var operationName     = operationElement.GetAttributeValue("Name");

                    var possibleMatches = model.FindDeclaredOperations(namespaceName + "." + operationName).ToArray();
                    ExceptionUtilities.Assert(possibleMatches.Any(), "Failed to find action or function import " + operationName);

                    IEdmOperation operation = null;
                    foreach (var possibleMatch in possibleMatches)
                    {
                        try
                        {
                            CompareOperationParameters(parameterElements, possibleMatch.Parameters);
                            operation = possibleMatch;
                            break;
                        }
                        catch (InvalidOperationException)
                        {
                            // Swallow exception for failed comparison
                        }
                    }

                    ExceptionUtilities.Assert(operation != null, "Failed to find a matching operation for " + operationName);

                    string returnTypeValue;
                    if (operationElement.TryGetAttributeValue("ReturnType", out returnTypeValue))
                    {
                        ExceptionUtilities.CheckObjectNotNull(operation.ReturnType, "Expected a return type for operation");
                        CompareTypeValue(returnTypeValue, operation.ReturnType);
                    }
                    else
                    {
                        var returnTypeElement = operationElement.EdmElements("ReturnType").SingleOrDefault();
                        if (returnTypeElement != null)
                        {
                            CompareType(returnTypeElement, operation.ReturnType);
                            // TODO: Enable this.
                            // CompareTypeFacets(propertyElement, propertyOnModel.Type);
                        }
                        else
                        {
                            ExceptionUtilities.Assert(operation.ReturnType == null, "Did not expect a return type for operation");
                        }
                    }

                    CompareBooleanAttribute(operationElement, "IsBound", operation.IsBound, false);

                    string entitySetPathValue;
                    if (operationElement.TryGetAttributeValue("EntitySetPath", out entitySetPathValue))
                    {
                        ExceptionUtilities.Assert(operation.EntitySetPath != null, "Expected a value for EntitySetPath");
                        CompareEntitySetPaths(entitySetPathValue, operation.EntitySetPath);
                    }
                    else
                    {
                        ExceptionUtilities.Assert(operation.EntitySetPath == null, "Did not expect a value for EntitySetPath");
                    }

                    bool isFunction = operationElement.Name.LocalName == "Function";
                    if (isFunction)
                    {
                        // Function specific verification
                        ExceptionUtilities.Assert(operation is IEdmFunction, "Model operation is not a function");

                        // TODO: Enable this.
                        // CompareBooleanAttribute(operationElement, "IsComposable", operation.IsComposable, false);
                    }
                    else
                    {
                        // Action specific verification
                        ExceptionUtilities.Assert(operation is IEdmAction, "Model operation is not an action");
                    }
                }
            }
        }
コード例 #12
0
        private static bool TryParseOperationParameters(string functionName, string parenthesisExpression, ParameterAliasValueAccessor paramAliasAccessor, IEdmOperation operation, out ICollection<OperationSegmentParameter> parsedSegementParameters)
        {
            ICollection<FunctionParameterToken> splitParameters;
            parsedSegementParameters = null;
            ODataUriParserConfiguration configuration = new ODataUriParserConfiguration(HardCodedTestModel.TestModel) { ParameterAliasValueAccessor = paramAliasAccessor };
            if (FunctionParameterParser.TrySplitOperationParameters(parenthesisExpression, configuration, out splitParameters))
            {
                parsedSegementParameters = FunctionCallBinder.BindSegmentParameters(configuration, operation, splitParameters);
                return true;
            }

            return false;
        }
コード例 #13
0
        /// <summary>
        /// Resolve an operation parameter's name with case insensitive enabled
        /// </summary>
        /// <param name="operation">The operation.</param>
        /// <param name="identifier">Name for the parameter.</param>
        /// <returns>The resolved operation parameter.</returns>
        internal static IEdmOperationParameter ResolveOpearationParameterNameCaseInsensitive(IEdmOperation operation, string identifier)
        {
            var list = operation.Parameters.Where(parameter => string.Equals(identifier, parameter.Name, StringComparison.OrdinalIgnoreCase)).ToList();

            if (list.Count > 1)
            {
                throw new ODataException(Strings.UriParserMetadata_MultipleMatchingParametersFound(identifier));
            }

            if (list.Count == 1)
            {
                return list.Single();
            }

            return null;
        }
コード例 #14
0
        /// <summary>
        /// Bind path segment's operation or operationImport's parameters.
        /// </summary>
        /// <param name="configuration">The ODataUriParserConfiguration.</param>
        /// <param name="functionOrOpertion">The function or operation.</param>
        /// <param name="segmentParameterTokens">The parameter tokens to be binded.</param>
        /// <returns>The binded semantic nodes.</returns>
        internal static List <OperationSegmentParameter> BindSegmentParameters(ODataUriParserConfiguration configuration, IEdmOperation functionOrOpertion, ICollection <FunctionParameterToken> segmentParameterTokens)
        {
            // TODO: HandleComplexOrCollectionParameterValueIfExists is temp work around for single copmlex or colleciton type, it can't handle nested complex or collection value.
            ICollection <FunctionParameterToken> parametersParsed = FunctionCallBinder.HandleComplexOrCollectionParameterValueIfExists(configuration.Model, functionOrOpertion, segmentParameterTokens, configuration.Resolver.EnableCaseInsensitive, configuration.EnableUriTemplateParsing);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);

            state.ImplicitRangeVariable = null;
            state.RangeVariables.Clear();
            MetadataBinder binder = new MetadataBinder(state);
            List <OperationSegmentParameter> boundParameters = new List <OperationSegmentParameter>();

            IDictionary <string, SingleValueNode> input = new Dictionary <string, SingleValueNode>(StringComparer.Ordinal);

            foreach (var paraToken in parametersParsed)
            {
                // TODO: considering another better exception
                if (paraToken.ValueToken is EndPathToken)
                {
                    throw new ODataException(Strings.MetadataBinder_ParameterNotInScope(
                                                 string.Format(CultureInfo.InvariantCulture, "{0}={1}", paraToken.ParameterName, (paraToken.ValueToken as EndPathToken).Identifier)));
                }

                SingleValueNode boundNode = (SingleValueNode)binder.Bind(paraToken.ValueToken);

                if (!input.ContainsKey(paraToken.ParameterName))
                {
                    input.Add(paraToken.ParameterName, boundNode);
                }
            }

            IDictionary <IEdmOperationParameter, SingleValueNode> result = configuration.Resolver.ResolveOperationParameters(functionOrOpertion, input);

            foreach (var item in result)
            {
                SingleValueNode boundNode = item.Value;

                // ensure node type is compatible with parameter type.
                var  sourceTypeReference    = boundNode.GetEdmTypeReference();
                bool sourceIsNullOrOpenType = (sourceTypeReference == null);
                if (!sourceIsNullOrOpenType)
                {
                    // if the node has been rewritten, no further conversion is needed.
                    if (!TryRewriteIntegralConstantNode(ref boundNode, item.Key.Type))
                    {
                        boundNode = MetadataBindingUtils.ConvertToTypeIfNeeded(boundNode, item.Key.Type);
                    }
                }

                OperationSegmentParameter boundParamer = new OperationSegmentParameter(item.Key.Name, boundNode);
                boundParameters.Add(boundParamer);
            }

            return(boundParameters);
        }
コード例 #15
0
 /// <summary>
 /// Create a <see cref="ODataParameterReader"/>.
 /// </summary>
 /// <param name="operation">The operation import whose parameters are being read.</param>
 /// <returns>The newly created <see cref="ODataParameterReader"/>.</returns>
 private ODataParameterReader CreateParameterReaderImplementation(IEdmOperation operation)
 {
     return(new ODataJsonLightParameterReader(this, operation));
 }
コード例 #16
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);
        }
コード例 #17
0
        private static ODataOperation CreateODataOperation(IEdmOperation operation, ProcedureLinkBuilder builder, EntityInstanceContext entityInstanceContext)
        {
            Contract.Assert(operation != null);
            Contract.Assert(builder != null);
            Contract.Assert(entityInstanceContext != null);

            ODataMetadataLevel metadataLevel = entityInstanceContext.SerializerContext.MetadataLevel;
            IEdmModel model = entityInstanceContext.EdmModel;

            if (ShouldOmitOperation(operation, builder, metadataLevel))
            {
                return null;
            }

            Uri target = builder.BuildLink(entityInstanceContext);
            if (target == null)
            {
                return null;
            }

            Uri baseUri = new Uri(entityInstanceContext.Url.CreateODataLink(new MetadataPathSegment()));
            Uri metadata = new Uri(baseUri, "#" + CreateMetadataFragment(operation));

            ODataOperation odataOperation;
            if (operation is IEdmAction)
            {
                odataOperation = new ODataAction();
            }
            else
            {
                odataOperation = new ODataFunction();
            }
            odataOperation.Metadata = metadata;

            // Always omit the title in minimal/no metadata modes.
            if (metadataLevel == ODataMetadataLevel.FullMetadata)
            {
                EmitTitle(model, operation, odataOperation);
            }

            // Omit the target in minimal/no metadata modes unless it doesn't follow conventions.
            if (!builder.FollowsConventions || metadataLevel == ODataMetadataLevel.FullMetadata)
            {
                odataOperation.Target = target;
            }

            return odataOperation;
        }
コード例 #18
0
        internal static bool ShouldOmitOperation(IEdmOperation operation, ProcedureLinkBuilder builder,
            ODataMetadataLevel metadataLevel)
        {
            Contract.Assert(builder != null);

            switch (metadataLevel)
            {
                case ODataMetadataLevel.MinimalMetadata:
                case ODataMetadataLevel.NoMetadata:
                    return operation.IsBound && builder.FollowsConventions;

                case ODataMetadataLevel.FullMetadata:
                default: // All values already specified; just keeping the compiler happy.
                    return false;
            }
        }
コード例 #19
0
        private static void ValidateNoError(IEdmModel model, IEdmOperation operation)
        {
            IEnumerable<EdmError> errorsFound = null;
            IEdmOperationParameter operationParameter = null;
            IEnumerable<IEdmNavigationProperty> navigationProperties = null;
            IEdmEntityType entityType = null;

            operation.TryGetRelativeEntitySetPath(model, out operationParameter, out navigationProperties, out entityType, out errorsFound);
            errorsFound.Should().HaveCount(0);
        }
コード例 #20
0
        /// <summary>
        /// Generates an function link following the OData URL conventions for the function <paramref name="function"/> and bound to the entity
        /// represented by <paramref name="entityContext"/>.
        /// </summary>
        /// <param name="entityContext">The <see cref="EntityInstanceContext"/> representing the entity for which the function link needs to be generated.</param>
        /// <param name="function">The function for which the function link needs to be generated.</param>
        /// <returns>The generated function link following OData URL conventions.</returns>
        public static Uri GenerateFunctionLink(this EntityInstanceContext entityContext, IEdmOperation function)
        {
            if (entityContext == null)
            {
                throw Error.ArgumentNull("entityContext");
            }
            if (function == null)
            {
                throw Error.ArgumentNull("function");
            }

            IEdmOperationParameter bindingParameter = function.Parameters.FirstOrDefault();

            if (bindingParameter == null || !bindingParameter.Type.IsEntity())
            {
                throw Error.Argument("function", SRResources.FunctionNotBoundToEntity, function.Name);
            }

            return(GenerateFunctionLink(entityContext, bindingParameter.Type.FullName(), function.Name, function.Parameters.Select(p => p.Name)));
        }
コード例 #21
0
        private static void ValidateError(IEdmModel model, IEdmOperation operation, EdmErrorCode expectedErrorCode, string expectedError)
        {
            IEnumerable<EdmError> errorsFound = null;
            IEdmOperationParameter operationParameter = null;
            IEnumerable<IEdmNavigationProperty> navigationProperties = null;
            IEdmEntityType entityType = null;

            operation.TryGetRelativeEntitySetPath(model, out operationParameter, out navigationProperties, out entityType, out errorsFound);
            errorsFound.Should().HaveCount(1);
            var errorsFoundList = errorsFound.ToList();
            errorsFoundList[0].ErrorCode.Should().Be(expectedErrorCode);
            errorsFoundList[0].ErrorMessage.Should().Be(expectedError);
        }
コード例 #22
0
ファイル: EdmUtil.cs プロジェクト: OpenSilver/odata.net
        internal static string FullyQualifiedName(IEdmVocabularyAnnotatable element)
        {
            IEdmSchemaElement schemaElement = element as IEdmSchemaElement;

            if (schemaElement != null)
            {
                IEdmOperation operation = schemaElement as IEdmOperation;
                if (operation != null)
                {
                    return(ParameterizedName(operation));
                }
                else
                {
                    return(schemaElement.FullName());
                }
            }
            else
            {
                IEdmEntityContainerElement containerElement = element as IEdmEntityContainerElement;
                if (containerElement != null)
                {
                    return(containerElement.Container.FullName() + "/" + containerElement.Name);
                }
                else
                {
                    IEdmProperty property = element as IEdmProperty;
                    if (property != null)
                    {
                        IEdmSchemaType declaringSchemaType = property.DeclaringType as IEdmSchemaType;
                        if (declaringSchemaType != null)
                        {
                            string propertyOwnerName = FullyQualifiedName(declaringSchemaType);
                            if (propertyOwnerName != null)
                            {
                                return(propertyOwnerName + "/" + property.Name);
                            }
                        }
                    }
                    else
                    {
                        IEdmOperationReturn    operationReturn;
                        IEdmEnumMember         enumMember;
                        IEdmOperationParameter parameter = element as IEdmOperationParameter;
                        if (parameter != null)
                        {
                            string parameterOwnerName = FullyQualifiedName(parameter.DeclaringOperation);
                            if (parameterOwnerName != null)
                            {
                                return(parameterOwnerName + "/" + parameter.Name);
                            }
                        }
                        else if ((enumMember = element as IEdmEnumMember) != null)
                        {
                            string enumMemberOwnerName = FullyQualifiedName(enumMember.DeclaringType);
                            if (enumMemberOwnerName != null)
                            {
                                return(enumMemberOwnerName + "/" + enumMember.Name);
                            }
                        }
                        else if ((operationReturn = element as IEdmOperationReturn) != null)
                        {
                            string operationName = FullyQualifiedName(operationReturn.DeclaringOperation);
                            if (operationName != null)
                            {
                                return(operationName + "/" + CsdlConstants.OperationReturnExternalTarget);
                            }
                        }
                    }
                }
            }

            return(null);
        }
コード例 #23
0
        private static void ValidateErrorInList(IEdmModel model, IEdmOperation operation, EdmErrorCode expectedErrorCode, string expectedError)
        {
            IEnumerable<EdmError> errorsFound = null;
            IEdmOperationParameter operationParameter = null;
            IEnumerable<IEdmNavigationProperty> navigationProperties = null;
            IEdmEntityType entityType = null;

            operation.TryGetRelativeEntitySetPath(model, out operationParameter, out navigationProperties, out entityType, out errorsFound);
            var error = errorsFound.SingleOrDefault(e => e.ErrorCode == expectedErrorCode);
            error.Should().NotBeNull();
            error.ErrorMessage.Should().Be(expectedError);
        }
コード例 #24
0
ファイル: EdmUtil.cs プロジェクト: slash-n-stash/odata.net
 /// <summary>
 /// Checks whether the <paramref name="annotatableOperation"/> has a MIME type annotation.
 /// </summary>
 /// <param name="model">The <see cref="IEdmModel"/> containing the annotation.</param>
 /// <param name="annotatableOperation">The <see cref="IEdmOperation"/> to check.</param>
 /// <returns>The (non-null) value of the MIME type annotation of the <paramref name="annotatableOperation"/> or null if no MIME type annotation exists.</returns>
 public static string GetMimeType(this IEdmModel model, IEdmOperation annotatableOperation)
 {
     return(GetStringAnnotationValue(model, annotatableOperation, EdmConstants.MimeTypeAttributeName, () => Strings.EdmUtil_NullValueForMimeTypeAnnotation));
 }
コード例 #25
0
ファイル: ODataOutputContext.cs プロジェクト: TomDu/odata.net
 /// <summary>
 /// Asynchronously creates an <see cref="ODataParameterWriter" /> to write a parameter payload.
 /// </summary>
 /// <param name="operation">The operation whose parameters will be written.</param>
 /// <returns>A running task for the created parameter writer.</returns>
 /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks>
 public virtual Task<ODataParameterWriter> CreateODataParameterWriterAsync(IEdmOperation operation)
 {
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Error);
 }
コード例 #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EdmApplyExpression"/> class.
 /// </summary>
 /// <param name="appliedOperation">Operation to apply.</param>
 /// <param name="arguments">Application arguments. Value may be null, in which case it is treated as an empty enumerable.</param>
 public EdmApplyExpression(IEdmOperation appliedOperation, params IEdmExpression[] arguments)
     : this(appliedOperation, (IEnumerable <IEdmExpression>)arguments)
 {
 }
コード例 #27
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="jsonLightInputContext">The input to read the payload from.</param>
        /// <param name="operation">The operation import whose parameters are being read.</param>
        internal ODataJsonLightParameterReader(ODataJsonLightInputContext jsonLightInputContext, IEdmOperation operation)
            : base(jsonLightInputContext, operation)
        {
            Debug.Assert(jsonLightInputContext != null, "jsonLightInputContext != null");
            Debug.Assert(jsonLightInputContext.ReadingResponse == false, "jsonLightInputContext.ReadingResponse == false");
            Debug.Assert(operation != null, "operationImport != null");

            this.jsonLightInputContext          = jsonLightInputContext;
            this.jsonLightParameterDeserializer = new ODataJsonLightParameterDeserializer(this, jsonLightInputContext);
            Debug.Assert(this.jsonLightInputContext.Model.IsUserModel(), "this.jsonLightInputContext.Model.IsUserModel()");
        }
コード例 #28
0
        /// <summary>
        /// Generates an function link following the OData URL conventions for the function <paramref name="function"/> and bound to the entity
        /// represented by <paramref name="entityContext"/>.
        /// </summary>
        /// <param name="entityContext">The <see cref="EntityInstanceContext"/> representing the entity for which the function link needs to be generated.</param>
        /// <param name="function">The function for which the function link needs to be generated.</param>
        /// <returns>The generated function link following OData URL conventions.</returns>
        public static Uri GenerateFunctionLink(this EntityInstanceContext entityContext, IEdmOperation function)
        {
            if (entityContext == null)
            {
                throw Error.ArgumentNull("entityContext");
            }
            if (function == null)
            {
                throw Error.ArgumentNull("function");
            }

            IEdmOperationParameter bindingParameter = function.Parameters.FirstOrDefault();
            if (bindingParameter == null || !bindingParameter.Type.IsEntity())
            {
                throw Error.Argument("function", SRResources.FunctionNotBoundToEntity, function.Name);
            }

            return GenerateFunctionLink(entityContext, bindingParameter.Type.FullName(), function.Name, function.Parameters.Select(p => p.Name));
        }
コード例 #29
0
 public static void SetIsDbFunction(this IEdmModel edmModel, IEdmOperation edmOperation, bool isDbFunction)
 {
     edmModel.SetAnnotationValue(edmOperation, new OeValueAnnotation <bool>(isDbFunction));
 }
コード例 #30
0
        internal static Uri GenerateFunctionLink(this ResourceContext resourceContext,
                                                 IEdmTypeReference bindingParameterType, IEdmOperation function,
                                                 IEnumerable <string> parameterNames)
        {
            IList <ODataPathSegment> functionPathSegments = resourceContext.GenerateBaseODataPathSegments();

            // generate link with cast if the navigation source type doesn't match the entity type the function is bound to.
            if (resourceContext.NavigationSource.EntityType() != bindingParameterType.Definition)
            {
                functionPathSegments.Add(new TypeSegment(bindingParameterType.Definition, null));
            }

            IList <OperationSegmentParameter> parameters = new List <OperationSegmentParameter>();

            // skip the binding parameter
            foreach (string param in parameterNames.Skip(1))
            {
                string value = "@" + param;
                parameters.Add(new OperationSegmentParameter(param, new ConstantNode(value, value)));
            }

            OperationSegment segment = new OperationSegment(new[] { function }, parameters, null);

            functionPathSegments.Add(segment);

            string functionLink = resourceContext.InternalUrlHelper.CreateODataLink(functionPathSegments);

            return(functionLink == null ? null : new Uri(functionLink));
        }
コード例 #31
0
        public static bool IsDbFunction(this IEdmModel edmModel, IEdmOperation edmOperation)
        {
            OeValueAnnotation <bool> valueAnnotation = edmModel.GetAnnotationValue <OeValueAnnotation <bool> >(edmOperation);

            return(valueAnnotation.Value);
        }
コード例 #32
0
        public void InvokeAvroAction()
        {
            ODataEntry product1 = new ODataEntry
            {
                TypeName   = "Microsoft.Test.OData.Services.PluggableFormat.Product",
                Properties = new[]
                {
                    new ODataProperty {
                        Name = "Id", Value = 1
                    },
                    new ODataProperty {
                        Name = "Name", Value = "Peach"
                    },
                    new ODataProperty
                    {
                        Name  = "Info",
                        Value = new ODataComplexValue()
                        {
                            TypeName   = "Microsoft.Test.OData.Services.PluggableFormat.ProductInfo",
                            Properties = new []
                            {
                                new ODataProperty {
                                    Name = "Site", Value = "G1"
                                },
                                new ODataProperty {
                                    Name = "Serial", Value = 1024L
                                },
                            }
                        }
                    },
                },
            };

            IEdmModel     model  = new PluggableFormatService(null).Format.LoadServiceModel();
            IEdmOperation action = model.FindDeclaredOperations("Microsoft.Test.OData.Services.PluggableFormat.AddProduct").Single();

            var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "Products/Microsoft.Test.OData.Services.PluggableFormat.AddProduct", UriKind.Absolute));

            requestMessage.Method = "POST";
            using (var mw = new ODataMessageWriter(requestMessage, GetAvroWriterSettings(), model))
            {
                var pw = mw.CreateODataParameterWriter(action);
                pw.WriteStart();
                var ew = pw.CreateEntryWriter("Value");
                {
                    ew.WriteStart(product1);
                    ew.WriteEnd();
                    ew.Flush();
                }

                pw.WriteValue("Override", true);
                pw.WriteEnd();
                pw.Flush();
            }

            var responseMessage = requestMessage.GetResponse();

            Assert.AreEqual(204, responseMessage.StatusCode);

            requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "Products(1)", UriKind.Absolute));
            requestMessage.SetHeader("Accept", "avro/binary");
            responseMessage = requestMessage.GetResponse();
            ODataEntry entry = null;

            using (var messageReader = new ODataMessageReader(responseMessage, GetAvroReaderSettings(), Model))
            {
                var reader = messageReader.CreateODataEntryReader();
                while (reader.Read())
                {
                    if (reader.State == ODataReaderState.EntryEnd)
                    {
                        entry = reader.Item as ODataEntry;
                    }
                }
            }

            Assert.IsNotNull(entry);
            Assert.IsTrue(TestHelper.EntryEqual(product1, entry));
        }
コード例 #33
0
        private bool IsExactMatch(IEdmOperation operation)
        {
            IEnumerator<IEdmExpression> parameterExpressionEnumerator = this.Arguments.GetEnumerator();
            foreach (IEdmOperationParameter parameter in operation.Parameters)
            {
                parameterExpressionEnumerator.MoveNext();
                IEnumerable<EdmError> recursiveErrors;
                if (!parameterExpressionEnumerator.Current.TryCast(parameter.Type, this.bindingContext, true, out recursiveErrors))
                {
                    return false;
                }
            }

            return true;
        }
コード例 #34
0
 /// <summary>
 /// Asynchronously create a <see cref="ODataParameterReader"/>.
 /// </summary>
 /// <param name="operation">The operation whose parameters are being read.</param>
 /// <returns>Task which when completed returns the newly created <see cref="ODataParameterReader"/>.</returns>
 public virtual Task <ODataParameterReader> CreateParameterReaderAsync(IEdmOperation operation)
 {
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Parameter);
 }
コード例 #35
0
ファイル: ODataPathParser.cs プロジェクト: sabyabr/odata.net
        /// <summary>
        /// Tries to find a single matching operation import for the given identifier, parametes, and binding type.
        /// </summary>
        /// <param name="identifier">The identifier from the URI.</param>
        /// <param name="parenthesisExpression">The parenthesis expression contianing parameters, if any.</param>
        /// <param name="bindingType">The current binding type or null if there isn't one.</param>
        /// <param name="configuration">The configuration of the parser.</param>
        /// <param name="boundParameters">The parsed parameters from the parenthesis expression.</param>
        /// <param name="matchingOperation">The single matching operation import if one could be determined.</param>
        /// <returns>Whether or not a matching operation import could be found.</returns>
        private static bool TryBindingParametersAndMatchingOperation(string identifier, string parenthesisExpression, IEdmType bindingType, ODataUriParserConfiguration configuration, out ICollection<OperationSegmentParameter> boundParameters, out IEdmOperation matchingOperation)
        {
            // If the name isn't fully qualified then it can't be a function or action.
            // When using extension, there may be function call with unqualified name. So loose the restriction here.
            if (identifier != null && identifier.IndexOf(".", StringComparison.Ordinal) == -1 && configuration.Resolver.GetType() == typeof(ODataUriResolver))
            {
                boundParameters = null;
                matchingOperation = null;
                return false;
            }

            // TODO: update code that is duplicate between operation and operation import, add more tests.
            matchingOperation = null;
            ICollection<FunctionParameterToken> splitParameters;
            if (!String.IsNullOrEmpty(parenthesisExpression))
            {
                if (!FunctionParameterParser.TrySplitOperationParameters(parenthesisExpression, configuration, out splitParameters))
                {
                    IEdmOperation possibleMatchingOperation = null;

                    // Look for an overload that returns an entity collection by the specified name. If so parthensis is just key parameters.
                    if (FunctionOverloadResolver.ResolveOperationFromList(identifier, new List<string>(), bindingType, configuration.Model, out possibleMatchingOperation, configuration.Resolver))
                    {
                        IEdmCollectionTypeReference collectionReturnType = possibleMatchingOperation.ReturnType as IEdmCollectionTypeReference;
                        if (collectionReturnType != null && collectionReturnType.ElementType().IsEntity())
                        {
                            matchingOperation = possibleMatchingOperation;
                            boundParameters = null;
                            return true;
                        }
                        else
                        {
                            throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier));
                        }
                    }

                    boundParameters = null;
                    return false;
                }
            }
            else
            {
                splitParameters = new Collection<FunctionParameterToken>();
            }

            // Resolve the specific overload.
            if (FunctionOverloadResolver.ResolveOperationFromList(identifier, splitParameters.Select(k => k.ParameterName).ToList(), bindingType, configuration.Model, out matchingOperation, configuration.Resolver))
            {
                boundParameters = FunctionCallBinder.BindSegmentParameters(configuration, matchingOperation, splitParameters);
                return true;
            }

            boundParameters = null;
            return false;
        }
コード例 #36
0
        internal static string CreateMetadataFragment(IEdmOperation operation)
        {
            // There can only be one entity container in OData V4.
            string actionName = operation.Name;
            string fragment = operation.Namespace + "." + actionName;

            return fragment;
        }
コード例 #37
0
ファイル: ODataPathParser.cs プロジェクト: sabyabr/odata.net
 /// <summary>
 /// Determines the entity set for segment.
 /// </summary>
 /// <param name="identifier">The identifier.</param>
 /// <param name="returnType">Type of the return.</param>
 /// <param name="segment">The segment.</param>
 /// <param name="targetset">The targetset.</param>
 /// <param name="singleOperation">The single operation.</param>
 /// <exception cref="ODataException">Throws and exception if entity set not specified.</exception>
 private static void DetermineEntitySetForSegment(string identifier, IEdmTypeReference returnType, ODataPathSegment segment, IEdmEntitySetBase targetset, IEdmOperation singleOperation)
 {
     if (returnType != null)
     {
         segment.TargetEdmNavigationSource = targetset;
         segment.TargetEdmType = returnType.Definition;
         segment.TargetKind = TargetKindFromType(segment.TargetEdmType);
         segment.SingleResult = !singleOperation.ReturnType.IsCollection();
     }
     else
     {
         segment.TargetEdmNavigationSource = null;
         segment.TargetEdmType = null;
         segment.TargetKind = RequestTargetKind.VoidOperation;
     }
 }
コード例 #38
0
        private Expression[] ProcessActionInvokePostBody(IODataRequestMessage message, IEdmOperation operation)
        {
            using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings(), this.DataSource.Model))
            {
                List<Expression> parameterValues = new List<Expression>();
                var parameterReader = messageReader.CreateODataParameterReader(operation);

                while (parameterReader.Read())
                {
                    switch (parameterReader.State)
                    {
                        case ODataParameterReaderState.Value:
                            {
                                object clrValue = ODataObjectModelConverter.ConvertPropertyValue(parameterReader.Value);
                                parameterValues.Add(Expression.Constant(clrValue));
                                break;
                            }
                        case ODataParameterReaderState.Collection:
                            {
                                ODataCollectionReader collectionReader = parameterReader.CreateCollectionReader();
                                object clrValue = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadCollectionParameterValue(collectionReader));
                                parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType()));
                                break;
                            }
                        case ODataParameterReaderState.Entry:
                            {
                                var entryReader = parameterReader.CreateEntryReader();
                                object clrValue = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadEntryParameterValue(entryReader));
                                parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType()));
                                break;
                            }
                        case ODataParameterReaderState.Feed:
                            {
                                IList collectionList = null;
                                var feedReader = parameterReader.CreateFeedReader();
                                while (feedReader.Read())
                                {
                                    if (feedReader.State == ODataReaderState.EntryEnd)
                                    {
                                        object clrItem = ODataObjectModelConverter.ConvertPropertyValue(feedReader.Item);
                                        if (collectionList == null)
                                        {
                                            Type itemType = clrItem.GetType();
                                            Type listType = typeof(List<>).MakeGenericType(new[] { itemType });
                                            collectionList = (IList)Utility.QuickCreateInstance(listType);
                                        }

                                        collectionList.Add(clrItem);
                                    }
                                }

                                parameterValues.Add(Expression.Constant(collectionList, collectionList.GetType()));
                                break;
                            }
                    }
                }

                return parameterValues.ToArray();
            }
        }
コード例 #39
0
        /// <summary>
        /// Get the string representation of <see cref="ODataPath"/>.
        /// mainly translate Context Url path.
        /// </summary>
        /// <param name="path">Path to perform the computation on.</param>
        /// <returns>The string representation of the Context Url path.</returns>
        public static string ToContextUrlPathString(this ODataPath path)
        {
            StringBuilder pathString = new StringBuilder();
            PathSegmentToContextUrlPathTranslator pathTranslator = PathSegmentToContextUrlPathTranslator.DefaultInstance;
            ODataPathSegment priorSegment = null;
            bool             foundOperationWithoutPath = false;

            foreach (ODataPathSegment segment in path)
            {
                OperationSegment       operationSegment       = segment as OperationSegment;
                OperationImportSegment operationImportSegment = segment as OperationImportSegment;
                if (operationImportSegment != null)
                {
                    IEdmOperationImport operationImport = operationImportSegment.OperationImports.FirstOrDefault();
                    Debug.Assert(operationImport != null);

                    EdmPathExpression pathExpression = operationImport.EntitySet as EdmPathExpression;
                    if (pathExpression != null)
                    {
                        Debug.Assert(priorSegment == null); // operation import is always the first segment?
                        pathString.Append(pathExpression.Path);
                    }
                    else
                    {
                        pathString = operationImport.Operation.ReturnType != null ?
                                     new StringBuilder(operationImport.Operation.ReturnType.FullName()) :
                                     new StringBuilder("Edm.Untyped");

                        foundOperationWithoutPath = true;
                    }
                }
                else if (operationSegment != null)
                {
                    IEdmOperation operation = operationSegment.Operations.FirstOrDefault();
                    Debug.Assert(operation != null);

                    if (operation.IsBound &&
                        priorSegment != null &&
                        operation.Parameters.First().Type.Definition == priorSegment.EdmType)
                    {
                        if (operation.EntitySetPath != null)
                        {
                            foreach (string pathSegment in operation.EntitySetPath.PathSegments.Skip(1))
                            {
                                pathString.Append('/');
                                pathString.Append(pathSegment);
                            }
                        }
                        else if (operationSegment.EntitySet != null)
                        {
                            // Is it correct to check EntitySet?
                            pathString = new StringBuilder(operationSegment.EntitySet.Name);
                        }
                        else
                        {
                            pathString = operation.ReturnType != null ?
                                         new StringBuilder(operation.ReturnType.FullName()) :
                                         new StringBuilder("Edm.Untyped");

                            foundOperationWithoutPath = true;
                        }
                    }
                }
                else
                {
                    if (foundOperationWithoutPath)
                    {
                        pathString = new StringBuilder(segment.EdmType.FullTypeName());
                        foundOperationWithoutPath = false;
                    }
                    else
                    {
                        pathString.Append(segment.TranslateWith(pathTranslator));
                    }
                }

                priorSegment = segment;
            }

            return(pathString.ToString().TrimStart('/'));
        }
コード例 #40
0
 public UnresolvedParameter(IEdmOperation declaringOperation, string name, EdmLocation location)
     : base(new EdmError[] { new EdmError(location, EdmErrorCode.BadUnresolvedParameter, Edm.Strings.Bad_UnresolvedParameter(name)) })
 {
     this.Name = name ?? string.Empty;
     this.DeclaringOperation = declaringOperation;
 }
コード例 #41
0
        public override IDictionary <IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary <string, SingleValueNode> input)
        {
            Dictionary <IEdmOperationParameter, SingleValueNode> result = new Dictionary <IEdmOperationParameter, SingleValueNode>(EqualityComparer <IEdmOperationParameter> .Default);

            foreach (var item in input)
            {
                IEdmOperationParameter functionParameter = null;
                if (EnableCaseInsensitive)
                {
                    functionParameter = ODataUriResolver.ResolveOpearationParameterNameCaseInsensitive(operation, item.Key);
                }
                else
                {
                    functionParameter = operation.FindParameter(item.Key);
                }

                // ensure parameter name existis
                if (functionParameter == null)
                {
                    throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name));
                }

                SingleValueNode newVal = item.Value;

                if (functionParameter.Type.IsEnum() &&
                    newVal is ConstantNode &&
                    newVal.TypeReference != null &&
                    newVal.TypeReference.IsString())
                {
                    string            text = ((ConstantNode)item.Value).Value as string;
                    ODataEnumValue    val;
                    IEdmTypeReference typeRef = functionParameter.Type;

                    if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val))
                    {
                        newVal = new ConstantNode(val, text, typeRef);
                    }
                }

                result.Add(functionParameter, newVal);
            }

            return(result);
        }
コード例 #42
0
        /// <summary>
        /// Create a <see cref="ODataParameterReader"/>.
        /// </summary>
        /// <param name="operationImport">The operation import whose parameters are being read.</param>
        /// <returns>The newly created <see cref="ODataParameterReader"/>.</returns>
        private ODataParameterReader CreateParameterReaderImplementation(IEdmOperationImport operationImport)
        {
            IEdmOperation operation = operationImport != null ? operationImport.Operation : null;

            return(new ODataJsonLightParameterReader(this, operation));
        }
コード例 #43
0
 /// <summary>
 /// Creates an <see cref="ODataParameterWriter" /> to write a parameter payload.
 /// </summary>
 /// <param name="operation">The operation whose parameters will be written.</param>
 /// <returns>The created parameter writer.</returns>
 /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks>
 public virtual ODataParameterWriter CreateODataParameterWriter(IEdmOperation operation)
 {
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Error);
 }
コード例 #44
0
        public virtual ODataOperation CreateODataOperation(IEdmOperation operation, ResourceSetContext resourceSetContext, ODataSerializerContext writeContext)
        {
            if (operation == null)
            {
                throw Error.ArgumentNull(nameof(operation));
            }

            if (resourceSetContext == null)
            {
                throw Error.ArgumentNull(nameof(resourceSetContext));
            }

            if (writeContext == null)
            {
                throw Error.ArgumentNull(nameof(writeContext));
            }

            ODataMetadataLevel metadataLevel = writeContext.MetadataLevel;
            IEdmModel          model         = writeContext.Model;

            if (metadataLevel != ODataMetadataLevel.Full)
            {
                return(null);
            }

            OperationLinkBuilder builder;

            builder = model.GetOperationLinkBuilder(operation);

            if (builder == null)
            {
                return(null);
            }

            Uri target = builder.BuildLink(resourceSetContext);

            if (target == null)
            {
                return(null);
            }

            Uri baseUri  = new Uri(writeContext.Request.CreateODataLink(MetadataSegment.Instance));
            Uri metadata = new Uri(baseUri, "#" + operation.FullName());

            ODataOperation odataOperation;
            IEdmAction     action = operation as IEdmAction;

            if (action != null)
            {
                odataOperation = new ODataAction();
            }
            else
            {
                odataOperation = new ODataFunction();
            }
            odataOperation.Metadata = metadata;

            // Always omit the title in minimal/no metadata modes.
            ODataResourceSerializer.EmitTitle(model, operation, odataOperation);

            // Omit the target in minimal/no metadata modes unless it doesn't follow conventions.
            if (metadataLevel == ODataMetadataLevel.Full || !builder.FollowsConventions)
            {
                odataOperation.Target = target;
            }

            return(odataOperation);
        }
コード例 #45
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:
            case EdmExpressionKind.AnnotationPath:
                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);
            }
        }
コード例 #46
0
 protected CsdlSemanticsOperationImport(CsdlSemanticsEntityContainer container, CsdlOperationImport operationImport, IEdmOperation operation)
     : base(operationImport)
 {
     this.container       = container;
     this.operationImport = operationImport;
     this.Operation       = operation;
 }
コード例 #47
0
        /// <summary>
        /// Creates an <see cref="ODataParameterWriter" /> to write a parameter payload.
        /// </summary>
        /// <param name="operation">The operation whose parameters will be written.</param>
        /// <returns>The created parameter writer.</returns>
        /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks>
        public override ODataParameterWriter CreateODataParameterWriter(IEdmOperation operation)
        {
            this.AssertSynchronous();

            return(this.CreateODataParameterWriterImplementation(operation));
        }
コード例 #48
0
        /// <summary>
        /// This is temp work around for $filter $orderby parameter expression which contains complex or collection
        ///     like "Fully.Qualified.Namespace.CanMoveToAddresses(addresses=[{\"Street\":\"NE 24th St.\",\"City\":\"Redmond\"},{\"Street\":\"Pine St.\",\"City\":\"Seattle\"}])";
        /// TODO:  $filter $orderby parameter expression which contains nested complex or collection should NOT be supported in this way
        ///     but should be parsed into token tree, and binded to node tree: parsedParameters.Select(p => this.bindMethod(p));
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="operation">IEdmFunction or IEdmOperation</param>
        /// <param name="parameterTokens">The tokens to bind.</param>
        /// <param name="enableCaseInsensitive">Whether to enable case-insensitive when resolving parameter name.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <returns>The FunctionParameterTokens with complex or collection values converted from string like "{...}", or "[..,..,..]".</returns>
        private static ICollection <FunctionParameterToken> HandleComplexOrCollectionParameterValueIfExists(IEdmModel model, IEdmOperation operation, ICollection <FunctionParameterToken> parameterTokens, bool enableCaseInsensitive, bool enableUriTemplateParsing = false)
        {
            ICollection <FunctionParameterToken> partiallyParsedParametersWithComplexOrCollection = new Collection <FunctionParameterToken>();

            foreach (FunctionParameterToken paraToken in parameterTokens)
            {
                FunctionParameterToken funcParaToken;
                IEdmOperationParameter functionParameter = operation.FindParameter(paraToken.ParameterName);
                if (enableCaseInsensitive && functionParameter == null)
                {
                    functionParameter = ODataUriResolver.ResolveOpearationParameterNameCaseInsensitive(operation, paraToken.ParameterName);

                    // The functionParameter can not be null here, else this method won't be called.
                    funcParaToken = new FunctionParameterToken(functionParameter.Name, paraToken.ValueToken);
                }
                else
                {
                    funcParaToken = paraToken;
                }

                FunctionParameterAliasToken aliasToken = funcParaToken.ValueToken as FunctionParameterAliasToken;
                if (aliasToken != null)
                {
                    aliasToken.ExpectedParameterType = functionParameter.Type;
                }

                LiteralToken valueToken = funcParaToken.ValueToken as LiteralToken;
                string       valueStr   = null;
                if (valueToken != null && (valueStr = valueToken.Value as string) != null && !string.IsNullOrEmpty(valueToken.OriginalText))
                {
                    var lexer = new ExpressionLexer(valueToken.OriginalText, true /*moveToFirstToken*/, false /*useSemicolonDelimiter*/, true /*parsingFunctionParameters*/);
                    if (lexer.CurrentToken.Kind == ExpressionTokenKind.BracketedExpression || lexer.CurrentToken.Kind == ExpressionTokenKind.BracedExpression)
                    {
                        object result;
                        UriTemplateExpression expression;

                        if (enableUriTemplateParsing && UriTemplateParser.TryParseLiteral(lexer.CurrentToken.Text, functionParameter.Type, out expression))
                        {
                            result = expression;
                        }
                        else if (!functionParameter.Type.IsStructured() && !functionParameter.Type.IsStructuredCollectionType())
                        {
                            // ExpressionTokenKind.BracketedExpression means text like [1,2]
                            // so now try convert it to collection type value:
                            result = ODataUriUtils.ConvertFromUriLiteral(valueStr, ODataVersion.V4, model, functionParameter.Type);
                        }
                        else
                        {
                            // For complex & colleciton of complex directly return the raw string.
                            partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken);
                            continue;
                        }

                        LiteralToken           newValueToken    = new LiteralToken(result, valueToken.OriginalText);
                        FunctionParameterToken newFuncParaToken = new FunctionParameterToken(funcParaToken.ParameterName, newValueToken);
                        partiallyParsedParametersWithComplexOrCollection.Add(newFuncParaToken);
                        continue;
                    }
                }

                partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken);
            }

            return(partiallyParsedParametersWithComplexOrCollection);
        }
コード例 #49
0
        /// <summary>
        /// Asynchronously creates an <see cref="ODataParameterWriter" /> to write a parameter payload.
        /// </summary>
        /// <param name="operation">The operation import whose parameters will be written.</param>
        /// <returns>A running task for the created parameter writer.</returns>
        /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks>
        public override Task <ODataParameterWriter> CreateODataParameterWriterAsync(IEdmOperation operation)
        {
            this.AssertAsynchronous();

            return(TaskUtils.GetTaskForSynchronousOperation(() => this.CreateODataParameterWriterImplementation(operation)));
        }
コード例 #50
0
        /// <summary>
        /// Resolve operation's parameters.
        /// </summary>
        /// <param name="operation">Current operation for parameters.</param>
        /// <param name="input">A dictionary the parameter list.</param>
        /// <returns>A dictionary containing resolved parameters.</returns>
        public virtual IDictionary<IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(IEdmOperation operation, IDictionary<string, SingleValueNode> input)
        {
            Dictionary<IEdmOperationParameter, SingleValueNode> result = new Dictionary<IEdmOperationParameter, SingleValueNode>(EqualityComparer<IEdmOperationParameter>.Default);
            foreach (var item in input)
            {
                IEdmOperationParameter functionParameter = null;
                if (EnableCaseInsensitive)
                {
                    functionParameter = ResolveOpearationParameterNameCaseInsensitive(operation, item.Key);
                }
                else
                {
                    functionParameter = operation.FindParameter(item.Key);
                }

                // ensure parameter name existis
                if (functionParameter == null)
                {
                    throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(item.Key, operation.Name));
                }

                result.Add(functionParameter, item.Value);
            }

            return result;
        }
コード例 #51
0
        /// <summary>
        /// Create the <see cref="OpenApiResponses"/> for a <see cref="IEdmOperation"/>
        /// </summary>
        /// <param name="context">The OData context.</param>
        /// <param name="operation">The Edm operation.</param>
        /// <param name="path">The OData path.</param>
        /// <returns>The created <see cref="OpenApiResponses"/>.</returns>
        public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperation operation, ODataPath path)
        {
            Utils.CheckArgumentNull(context, nameof(context));
            Utils.CheckArgumentNull(operation, nameof(operation));
            Utils.CheckArgumentNull(path, nameof(path));

            OpenApiResponses responses = new();

            if (operation.IsAction() && operation.ReturnType == null)
            {
                responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse());
            }
            else
            {
                OpenApiSchema schema;
                if (operation.ReturnType.IsCollection())
                {
                    // Get the entity type of the previous segment
                    IEdmEntityType entityType = path.Segments.Reverse().Skip(1)?.Take(1)?.FirstOrDefault()?.EntityType;
                    schema = new OpenApiSchema
                    {
                        Title      = entityType == null ? null : $"Collection of {entityType.Name}",
                        Type       = "object",
                        Properties = new Dictionary <string, OpenApiSchema>
                        {
                            {
                                "value", context.CreateEdmTypeSchema(operation.ReturnType)
                            }
                        }
                    };
                }
                else if (operation.ReturnType.IsPrimitive())
                {
                    // A property or operation response that is of a primitive type is represented as an object with a single name/value pair,
                    // whose name is value and whose value is a primitive value.
                    schema = new OpenApiSchema
                    {
                        Type       = "object",
                        Properties = new Dictionary <string, OpenApiSchema>
                        {
                            {
                                "value", context.CreateEdmTypeSchema(operation.ReturnType)
                            }
                        }
                    };
                }
                else
                {
                    schema = context.CreateEdmTypeSchema(operation.ReturnType);
                }

                string mediaType = Constants.ApplicationJsonMediaType;
                if (operation.ReturnType.AsPrimitive()?.PrimitiveKind() == EdmPrimitiveTypeKind.Stream)
                {
                    // Responses of types Edm.Stream should be application/octet-stream
                    mediaType = Constants.ApplicationOctetStreamMediaType;
                }

                OpenApiResponse response = new()
                {
                    Description = "Success",
                    Content     = new Dictionary <string, OpenApiMediaType>
                    {
                        {
                            mediaType,
                            new OpenApiMediaType
                            {
                                Schema = schema
                            }
                        }
                    }
                };
                responses.Add(context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, response);
            }

            if (context.Settings.ErrorResponsesAsDefault)
            {
                responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
            }
            else
            {
                responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse());
                responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse());
            }

            return(responses);
        }
コード例 #52
0
 /// <summary>
 /// Build a segment representing a call to an operation - action, function, or service operation.
 /// </summary>
 /// <param name="operation">A single operation import that this segment will represent.</param>
 /// <param name="parameters">The list of parameters supplied to this segment.</param>
 /// <param name="entitySet">The <see cref="IEdmEntitySetBase"/> containing the entities that this function returns.</param>
 public OperationSegment(IEdmOperation operation, IEnumerable <OperationSegmentParameter> parameters, IEdmEntitySetBase entitySet)
     : this(operation, entitySet)
 {
     this.parameters = new ReadOnlyCollection <OperationSegmentParameter>(parameters == null ? new List <OperationSegmentParameter>() : parameters.ToList());
 }
コード例 #53
0
        internal bool CheckMethodsInBaseClass(IEdmStructuredType structuredType, IEdmOperation operation, Dictionary<IEdmStructuredType, List<IEdmOperation>> boundOperationsMap)
        {
            if (structuredType != null)
            {
                List<IEdmOperation> operations;
                if (boundOperationsMap.TryGetValue(structuredType, out operations))
                {
                    foreach (var op in operations)
                    {
                        var targetParameter = operation.Parameters.ToList();
                        var checkParameter = op.Parameters.ToList();
                        if (operation.Name == op.Name && targetParameter.Count == checkParameter.Count)
                        {
                            var areSame = true;
                            for (var i = 1; i < targetParameter.Count; ++i)
                            {
                                var targetParameterType = targetParameter[i].Type;
                                var checkParameterType = checkParameter[i].Type;
                                if (!targetParameterType.Definition.Equals(checkParameterType.Definition)
                                    || targetParameterType.IsNullable != checkParameterType.IsNullable)
                                {
                                    areSame = false;
                                    break;
                                }
                            }

                            if (areSame)
                            {
                                return true;
                            }
                        }
                    }
                }

                return CheckMethodsInBaseClass(structuredType.BaseType, operation, boundOperationsMap);
            }

            return false;
        }
コード例 #54
0
 private static void AddProcedureLinkBuilder(IEdmModel model, IEdmOperation operation, ProcedureConfiguration procedure)
 {
     if (procedure.BindingParameter.TypeConfiguration.Kind == EdmTypeKind.Entity)
     {
         ActionConfiguration actionConfiguration = procedure as ActionConfiguration;
         IEdmAction action = operation as IEdmAction;
         FunctionConfiguration functionConfiguration = procedure as FunctionConfiguration;
         IEdmFunction function = operation as IEdmFunction;
         if (actionConfiguration != null && actionConfiguration.GetActionLink() != null && action != null)
         {
             model.SetActionLinkBuilder(
                 action,
                 new ActionLinkBuilder(actionConfiguration.GetActionLink(), actionConfiguration.FollowsConventions));
         }
         else if (functionConfiguration != null && functionConfiguration.GetFunctionLink() != null && function != null)
         {
             model.SetFunctionLinkBuilder(
                 function,
                 new FunctionLinkBuilder(functionConfiguration.GetFunctionLink(), functionConfiguration.FollowsConventions));
         }
     }
 }
コード例 #55
0
 public override IDictionary<IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(
     IEdmOperation operation, IDictionary<string, SingleValueNode> input)
 {
     return _stringAsEnum.ResolveOperationParameters(operation, input);
 }
コード例 #56
0
        private static bool TryParseOperationParameters(string functionName, string parenthesisExpression, IEdmOperation operation, out ICollection<OperationSegmentParameter> parsedSegementParameters, bool enableUriTemplateParsing = false)
        {
            ICollection<FunctionParameterToken> splitParameters;
            parsedSegementParameters = null;
            ODataUriParserConfiguration configuration = new ODataUriParserConfiguration(HardCodedTestModel.TestModel) { EnableUriTemplateParsing = enableUriTemplateParsing };
            if (FunctionParameterParser.TrySplitOperationParameters(parenthesisExpression, configuration, out splitParameters))
            {
                parsedSegementParameters = FunctionCallBinder.BindSegmentParameters(configuration, operation, splitParameters);
                return true;
            }

            return false;
        }
コード例 #57
0
        /// <summary>
        /// Generates a function link following the OData URL conventions for the function <paramref name="function"/> and bound to the
        /// collection of entity represented by <paramref name="resourceSetContext"/>.
        /// </summary>
        /// <param name="resourceSetContext">The <see cref="ResourceSetContext"/> representing the feed for which the function link needs to be generated.</param>
        /// <param name="function">The function for which the function link needs to be generated.</param>
        /// <returns>The generated function link following OData URL conventions.</returns>
        public static Uri GenerateFunctionLink(this ResourceSetContext resourceSetContext, IEdmOperation function)
        {
            if (resourceSetContext == null)
            {
                throw Error.ArgumentNull("resourceSetContext");
            }

            if (function == null)
            {
                throw Error.ArgumentNull("function");
            }

            IEdmOperationParameter bindingParameter = function.Parameters.FirstOrDefault();

            if (bindingParameter == null ||
                !bindingParameter.Type.IsCollection() ||
                !((IEdmCollectionType)bindingParameter.Type.Definition).ElementType.IsEntity())
            {
                throw Error.Argument("function", SRResources.FunctionNotBoundToCollectionOfEntity, function.Name);
            }

            return(GenerateFunctionLink(resourceSetContext, bindingParameter.Type, function,
                                        function.Parameters.Select(p => p.Name)));
        }
コード例 #58
0
 internal static void EmitTitle(IEdmModel model, IEdmOperation operation, ODataOperation odataAction)
 {
     // The title should only be emitted in full metadata.
     OperationTitleAnnotation titleAnnotation = model.GetOperationTitleAnnotation(operation);
     if (titleAnnotation != null)
     {
         odataAction.Title = titleAnnotation.Title;
     }
     else
     {
         odataAction.Title = operation.Name;
     }
 }
コード例 #59
0
        internal static Uri GenerateActionLink(this ResourceContext resourceContext,
                                               IEdmTypeReference bindingParameterType, IEdmOperation action)
        {
            Contract.Assert(resourceContext != null);
            if (resourceContext.NavigationSource is IEdmContainedEntitySet)
            {
                return(null);
            }

            IList <ODataPathSegment> actionPathSegments = resourceContext.GenerateBaseODataPathSegments();

            // generate link with cast if the navigation source doesn't match the entity type the action is bound to.
            if (resourceContext.NavigationSource.EntityType() != bindingParameterType.Definition)
            {
                actionPathSegments.Add(new TypeSegment((IEdmEntityType)bindingParameterType.Definition, null));
                // entity set can be null
            }

            OperationSegment operationSegment = new OperationSegment(new[] { action }, null);

            actionPathSegments.Add(operationSegment);

            string actionLink = resourceContext.InternalUrlHelper.CreateODataLink(actionPathSegments);

            return(actionLink == null ? null : new Uri(actionLink));
        }