Exemple #1
0
        public void CsdlUnnamedTypeDefinitionToStringTest()
        {
            const string csdl =
                @"<?xml version=""1.0"" encoding=""utf-16""?>
<Schema Namespace=""Namespace"" Alias=""Alias"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
  <EntityType Name=""AstonishingEntity"">
    <Key>
      <PropertyRef Name=""Id"" />
    </Key>
    <Property Name=""Id"" Type=""Int32"" Nullable=""false"" />
  </EntityType>
  <Function Name=""Function1""><ReturnType Type=""Edm.Int32""/>
    <Parameter Name=""P1"" Type=""Collection(Edm.Int32)"" />
    <Parameter Name=""P2"" Type=""Ref(Namespace.AstonishingEntity)"" />
  </Function>
</Schema>";
            IEdmModel model;
            IEnumerable <EdmError> errors;
            bool parsed = CsdlReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(csdl)) }, out model, out errors);

            Assert.IsTrue(parsed, "parsed");
            Assert.IsTrue(errors.Count() == 0, "No errors");

            IEdmOperation           operation  = (IEdmOperation)(model.FindOperations("Namespace.Function1")).First();
            IEdmCollectionType      collection = (IEdmCollectionType)operation.FindParameter("P1").Type.Definition;
            IEdmEntityReferenceType entityRef  = (IEdmEntityReferenceType)operation.FindParameter("P2").Type.Definition;

            Assert.AreEqual("Collection([Edm.Int32 Nullable=True])", collection.ToString(), "To string correct");
            Assert.AreEqual("EntityReference(Namespace.AstonishingEntity)", entityRef.ToString(), "To string correct");
        }
Exemple #2
0
        public void CanCreateEdmModel_WithDateAndTimeOfDay_AsFunctionParameter(Type paramType, string expect)
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var functionBuilder = movie.Function("FunctionName").Returns <int>();

            functionBuilder.Parameter(paramType, "p1");

            MethodInfo method = typeof(OperationConfiguration).GetMethod("CollectionParameter", BindingFlags.Instance | BindingFlags.Public);

            method.MakeGenericMethod(paramType).Invoke(functionBuilder, new[] { "p2" });

            // Act
            IEdmModel model = builder.GetEdmModel();

            //Assert
            IEdmOperation function = Assert.Single(model.SchemaElements.OfType <IEdmFunction>());

            Assert.Equal("FunctionName", function.Name);

            IEdmOperationParameter parameter = function.FindParameter("p1");

            Assert.Equal(expect, parameter.Type.FullName());
            Assert.Equal(TypeHelper.IsNullable(paramType), parameter.Type.IsNullable);

            parameter = function.FindParameter("p2");
            Assert.Equal("Collection(" + expect + ")", parameter.Type.FullName());
            Assert.Equal(TypeHelper.IsNullable(paramType), parameter.Type.IsNullable);
        }
        /// <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);
        }
Exemple #4
0
        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)
                    {
                        object result;
                        UriTemplateExpression expression;

                        if (enableUriTemplateParsing && UriTemplateParser.TryParseLiteral(lexer.CurrentToken.Text, functionParameter.Type, out expression))
                        {
                            result = expression;
                        }
                        else
                        {
                            // ExpressionTokenKind.BracketedExpression means text like [{\"Street\":\"NE 24th St.\",\"City\":\"Redmond\"},{\"Street\":\"Pine St.\",\"City\":\"Seattle\"}]
                            // so now try convert it into complex or collection type value:
                            result = ODataUriUtils.ConvertFromUriLiteral(valueStr, ODataVersion.V4, model, functionParameter.Type);
                        }

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

                partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken);
            }

            return(partiallyParsedParametersWithComplexOrCollection);
        }
Exemple #5
0
        public void GetEdmModel_SetsDateTimeAsParameterType_WorksForDefaultConverter()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var functionBuilder = movie.Function("DateTimeFunction");

            functionBuilder.Parameter <DateTime>("dateTime");
            functionBuilder.Parameter <DateTime?>("nullableDateTime");
            functionBuilder.CollectionParameter <DateTime>("collectionDateTime");
            functionBuilder.CollectionParameter <DateTime?>("nullableCollectionDateTime");
            functionBuilder.Returns <DateTime>();

            // Act
            IEdmModel model = builder.GetEdmModel();

            //Assert
            IEdmOperation function = Assert.Single(model.SchemaElements.OfType <IEdmFunction>());

            Assert.Equal("DateTimeFunction", function.Name);

            Assert.Equal("Edm.DateTimeOffset", function.ReturnType.FullName());
            Assert.False(function.ReturnType.IsNullable);

            IEdmOperationParameter parameter = function.FindParameter("dateTime");

            Assert.Equal("Edm.DateTimeOffset", parameter.Type.FullName());
            Assert.False(parameter.Type.IsNullable);

            parameter = function.FindParameter("nullableDateTime");
            Assert.Equal("Edm.DateTimeOffset", parameter.Type.FullName());
            Assert.True(parameter.Type.IsNullable);

            parameter = function.FindParameter("collectionDateTime");
            Assert.Equal("Collection(Edm.DateTimeOffset)", parameter.Type.FullName());
            Assert.False(parameter.Type.IsNullable);

            parameter = function.FindParameter("nullableCollectionDateTime");
            Assert.Equal("Collection(Edm.DateTimeOffset)", parameter.Type.FullName());
            Assert.True(parameter.Type.IsNullable);
        }
Exemple #6
0
        public void GetEdmModel_SetsNullableIffParameterTypeIsNullable()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var actionBuilder = movie.Action("Watch");

            actionBuilder.Parameter <int>("int");
            actionBuilder.Parameter <Nullable <int> >("nullableOfInt");
            actionBuilder.Parameter <string>("string");

            // Act
            IEdmModel model = builder.GetEdmModel();

            //Assert
            IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>());

            Assert.False(action.FindParameter("int").Type.IsNullable);
            Assert.True(action.FindParameter("nullableOfInt").Type.IsNullable);
            Assert.True(action.FindParameter("string").Type.IsNullable);
        }
Exemple #7
0
        public void GetEdmModel_SetsNullableIfParameterTypeIsReferenceType()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var functionBuilder = movie.Function("Watch");

            functionBuilder.Parameter <string>("string").Nullable = false;
            functionBuilder.Parameter <string>("nullaleString");

            functionBuilder.Parameter <Address>("address").Nullable = false;
            functionBuilder.Parameter <Address>("nullableAddress");

            functionBuilder.CollectionParameter <Address>("addresses").Nullable = false;
            functionBuilder.CollectionParameter <Address>("nullableAddresses");
            functionBuilder.Returns <int>();

            // Act
            IEdmModel model = builder.GetEdmModel();

            //Assert
            IEdmOperation function = Assert.Single(model.SchemaElements.OfType <IEdmFunction>());

            Assert.False(function.FindParameter("string").Type.IsNullable);
            Assert.True(function.FindParameter("nullaleString").Type.IsNullable);

            Assert.False(function.FindParameter("address").Type.IsNullable);
            Assert.True(function.FindParameter("nullableAddress").Type.IsNullable);

            Assert.False(function.FindParameter("addresses").Type.IsNullable);
            Assert.True(function.FindParameter("nullableAddresses").Type.IsNullable);
        }
        public void GetEdmModel_SetsNullableIfParameterTypeIsReferenceType()
        {
            // Arrange
            ODataModelBuilder builder             = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();
            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;
            var actionBuilder = movie.Action("Watch");

            actionBuilder.Parameter <string>("string").OptionalParameter = false;
            actionBuilder.Parameter <string>("nullaleString");

            actionBuilder.Parameter <Address>("address").OptionalParameter = false;
            actionBuilder.Parameter <Address>("nullableAddress");

            actionBuilder.EntityParameter <Customer>("customer").OptionalParameter = false;
            actionBuilder.EntityParameter <Customer>("nullableCustomer");

            actionBuilder.CollectionParameter <Address>("addresses").OptionalParameter = false;
            actionBuilder.CollectionParameter <Address>("nullableAddresses");

            actionBuilder.CollectionEntityParameter <Customer>("customers").OptionalParameter = false;
            actionBuilder.CollectionEntityParameter <Customer>("nullableCustomers");

            // Act
            IEdmModel model = builder.GetEdmModel();

            //Assert
            IEdmOperation action = Assert.Single(model.SchemaElements.OfType <IEdmAction>());

            Assert.False(action.FindParameter("string").Type.IsNullable);
            Assert.True(action.FindParameter("nullaleString").Type.IsNullable);

            Assert.False(action.FindParameter("address").Type.IsNullable);
            Assert.True(action.FindParameter("nullableAddress").Type.IsNullable);

            Assert.False(action.FindParameter("customer").Type.IsNullable);
            Assert.True(action.FindParameter("nullableCustomer").Type.IsNullable);

            Assert.False(action.FindParameter("addresses").Type.IsNullable);
            Assert.True(action.FindParameter("nullableAddresses").Type.IsNullable);

            // Follow up: https://github.com/OData/odata.net/issues/98
            // Assert.False(action.FindParameter("customers").Type.IsNullable);
            Assert.True(action.FindParameter("nullableCustomers").Type.IsNullable);
        }
Exemple #9
0
        public void AmbiguousOperationTest()
        {
            string csdl = @"
<Schema Namespace=""DefaultNamespace"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
    <Term Name=""Annotation"" Type=""Edm.Int32"" />
    <EntityType Name=""Entity"" >
        <Key>
            <PropertyRef Name=""ID"" />
        </Key>
        <Property Name=""ID"" Type=""Edm.Int32"" Nullable=""False"" />
    </EntityType>
    <Function Name=""Function"">
        <Parameter Name=""Parameter"" Type=""Edm.String"" />
        <Parameter Name=""Parameter2"" Type=""Ref(DefaultNamespace.Entity)"" />
        <ReturnType Type=""Edm.Int32"" />
    </Function>
    <Function Name=""Function"">
        <Parameter Name=""Parameter"" Type=""Edm.String"" />
        <Parameter Name=""Parameter2"" Type=""Ref(DefaultNamespace.Entity)"" />
        <ReturnType Type=""Edm.Int32"" />
    </Function>
    <Function Name=""Function"">
        <Parameter Name=""Parameter"" Type=""Edm.String"" />
        <Parameter Name=""Parameter2"" Type=""Ref(DefaultNamespace.Entity)"" />
        <ReturnType Type=""Edm.Int32"" />
    </Function>
    <Annotations Target=""DefaultNamespace.Function(Edm.String, Ref(DefaultNamespace.Entity))"">
        <Annotation Term=""AnnotationNamespace.Annotation"">
            <Int>42</Int>
        </Annotation>
    </Annotations>
</Schema>";

            IEdmModel model;
            IEnumerable <EdmError> errors;
            bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(csdl)) }, out model, out errors);

            Assert.IsTrue(parsed, "parsed");
            Assert.IsTrue(errors.Count() == 0, "No errors");

            IEdmVocabularyAnnotation annotation         = model.VocabularyAnnotations.First();
            IEdmOperation            firstOperation     = model.FindOperations("DefaultNamespace.Function").First();
            IEdmOperation            ambiguousOperation = annotation.Target as IEdmOperation;

            Assert.IsNotNull(ambiguousOperation, "Function not null");
            Assert.AreEqual(EdmSchemaElementKind.Function, ambiguousOperation.SchemaElementKind, "Correct schema element kind");
            Assert.IsNull(ambiguousOperation.ReturnType, "Null return type");
            Assert.AreEqual("DefaultNamespace", ambiguousOperation.Namespace, "Correct namespace");
            Assert.AreEqual(firstOperation.Parameters.First(), ambiguousOperation.Parameters.First(), "Function gets parameters from first function");
            Assert.AreEqual(firstOperation.FindParameter("Parameter"), ambiguousOperation.FindParameter("Parameter"), "Find parameter defers to first function");
        }
Exemple #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)
                {
                    var list = operation.Parameters.Where(parameter => string.Equals(item.Key, parameter.Name, StringComparison.OrdinalIgnoreCase)).ToList();
                    if (list.Count == 1)
                    {
                        functionParameter = list.Single();
                    }
                    else if (list.Count > 1)
                    {
                        // TODO: fix loc strings.
                        throw new ODataException("More than one parameter match the name '" + item.Key + "' were found.");
                    }
                }
                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.TypeReference.IsString()) && newVal is ConstantNode)
                {
                    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);
        }
        private static ICollection <FunctionParameterToken> HandleComplexOrCollectionParameterValueIfExists(IEdmModel model, IEdmOperation functionOrOpertion, ICollection <FunctionParameterToken> parameterTokens, bool enableUriTemplateParsing = false)
        {
            ICollection <FunctionParameterToken> partiallyParsedParametersWithComplexOrCollection = new Collection <FunctionParameterToken>();

            foreach (FunctionParameterToken funcParaToken in parameterTokens)
            {
                LiteralToken valueToken = funcParaToken.ValueToken as LiteralToken;
                string       valueStr   = null;
                if (valueToken != null && (valueStr = valueToken.Value as string) != null)
                {
                    var lexer = new ExpressionLexer(valueStr, true /*moveToFirstToken*/, false /*useSemicolonDelimiter*/, true /*parsingFunctionParameters*/);
                    if (lexer.CurrentToken.Kind == ExpressionTokenKind.BracketedExpression)
                    {
                        var functionParameter = functionOrOpertion.FindParameter(funcParaToken.ParameterName);
                        if (functionParameter == null)
                        {
                            throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(funcParaToken.ParameterName, functionOrOpertion.Name));
                        }

                        object result;
                        UriTemplateExpression expression;

                        if (enableUriTemplateParsing && UriTemplateParser.TryParseLiteral(lexer.CurrentToken.Text, functionParameter.Type, out expression))
                        {
                            result = expression;
                        }
                        else
                        {
                            // ExpressionTokenKind.BracketedExpression means text like [{\"Street\":\"NE 24th St.\",\"City\":\"Redmond\"},{\"Street\":\"Pine St.\",\"City\":\"Seattle\"}]
                            // so now try convert it into complex or collection type value:
                            result = ODataUriUtils.ConvertFromUriLiteral(valueStr, ODataVersion.V4, model, functionParameter.Type);
                        }

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

                partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken);
            }

            return(partiallyParsedParametersWithComplexOrCollection);
        }
Exemple #12
0
        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.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>();

            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);

                // ensure parameter name existis
                var functionParameter = functionOrOpertion.FindParameter(paraToken.ParameterName);
                if (functionParameter == null)
                {
                    throw new ODataException(Strings.ODataParameterWriterCore_ParameterNameNotFoundInOperation(paraToken.ParameterName, functionOrOpertion.Name));
                }

                // ensure node type is compatible with parameter type.
                var  sourceTypeReference    = boundNode.GetEdmTypeReference();
                bool sourceIsNullOrOpenType = (sourceTypeReference == null);
                if (!sourceIsNullOrOpenType)
                {
                    boundNode = MetadataBindingUtils.ConvertToTypeIfNeeded(boundNode, functionParameter.Type);
                }

                OperationSegmentParameter boundParamer = new OperationSegmentParameter(paraToken.ParameterName, boundNode);
                boundParameters.Add(boundParamer);
            }

            return(boundParameters);
        }
Exemple #13
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);
        }
Exemple #14
0
        /// <summary>
        /// Resolve operation's parameters.
        /// </summary>
        /// <param name="operation">Current operation for parameters.</param>
        /// <param name="input">A dictionary the paramenter 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)
                {
                    var list = operation.Parameters.Where(parameter => string.Equals(item.Key, parameter.Name, StringComparison.OrdinalIgnoreCase)).ToList();
                    if (list.Count == 1)
                    {
                        functionParameter = list.Single();
                    }
                    else if (list.Count > 1)
                    {
                        // TODO: fix loc strings.
                        throw new ODataException("More than one parameter match the name '" + item.Key + "' were found.");
                    }
                }
                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);
        }
Exemple #15
0
        private IEdmVocabularyAnnotatable ComputeTarget()
        {
            if (this.targetContext != null)
            {
                return(this.targetContext);
            }
            else
            {
                Debug.Assert(this.annotationsContext != null, "Annotation must either have a target context or annotations context");
                string              target              = this.annotationsContext.Annotations.Target;
                string[]            targetSegments      = target.Split('/');
                int                 targetSegmentsCount = targetSegments.Length;
                IEdmEntityContainer container;

                if (targetSegmentsCount == 1)
                {
                    string         elementName = targetSegments[0];
                    IEdmSchemaType type        = this.schema.FindType(elementName);
                    if (type != null)
                    {
                        return(type);
                    }

                    IEdmTerm term = this.schema.FindTerm(elementName);
                    if (term != null)
                    {
                        return(term);
                    }

                    IEdmOperation operation = this.FindParameterizedOperation(elementName, this.Schema.FindOperations, this.CreateAmbiguousOperation);
                    if (operation != null)
                    {
                        return(operation);
                    }

                    container = this.schema.FindEntityContainer(elementName);
                    if (container != null)
                    {
                        return(container);
                    }

                    return(new UnresolvedType(this.Schema.UnresolvedName(targetSegments[0]), this.Location));
                }

                if (targetSegmentsCount == 2)
                {
                    container = this.schema.FindEntityContainer(targetSegments[0]);
                    if (container != null)
                    {
                        // Using the methods here results in a much faster lookup as it uses a dictionary instead of using the list of container elements.
                        IEdmEntityContainerElement containerElement = container.FindEntitySetExtended(targetSegments[1])
                                                                      ?? container.FindSingletonExtended(targetSegments[1]) as IEdmEntityContainerElement;
                        if (containerElement != null)
                        {
                            return(containerElement);
                        }

                        IEdmOperationImport operationImport = FindParameterizedOperationImport(targetSegments[1], container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport);
                        if (operationImport != null)
                        {
                            return(operationImport);
                        }

                        return(new UnresolvedEntitySet(targetSegments[1], container, this.Location));
                    }

                    IEdmSchemaType type = this.schema.FindType(targetSegments[0]);
                    if (type != null)
                    {
                        IEdmStructuredType structuredType;
                        IEdmEnumType       enumType;
                        if ((structuredType = type as IEdmStructuredType) != null)
                        {
                            IEdmProperty property = structuredType.FindProperty(targetSegments[1]);
                            if (property != null)
                            {
                                return(property);
                            }

                            return(new UnresolvedProperty(structuredType, targetSegments[1], this.Location));
                        }
                        else if ((enumType = type as IEdmEnumType) != null)
                        {
                            foreach (IEdmEnumMember member in enumType.Members)
                            {
                                if (String.Equals(member.Name, targetSegments[1], StringComparison.OrdinalIgnoreCase))
                                {
                                    return(member);
                                }
                            }

                            return(new UnresolvedEnumMember(targetSegments[1], enumType, this.Location));
                        }
                    }

                    IEdmOperation operation = this.FindParameterizedOperation(targetSegments[0], this.Schema.FindOperations, this.CreateAmbiguousOperation);
                    if (operation != null)
                    {
                        // $ReturnType
                        if (targetSegments[1] == CsdlConstants.OperationReturnExternalTarget)
                        {
                            if (operation.ReturnType != null)
                            {
                                return(operation.GetReturn());
                            }

                            return(new UnresolvedReturn(operation, this.Location));
                        }

                        IEdmOperationParameter parameter = operation.FindParameter(targetSegments[1]);
                        if (parameter != null)
                        {
                            return(parameter);
                        }

                        return(new UnresolvedParameter(operation, targetSegments[1], this.Location));
                    }

                    return(new UnresolvedProperty(new UnresolvedEntityType(this.Schema.UnresolvedName(targetSegments[0]), this.Location), targetSegments[1], this.Location));
                }

                if (targetSegmentsCount == 3)
                {
                    // The only valid target with three segments is a function parameter, or an operation return.
                    string containerName = targetSegments[0];
                    string operationName = targetSegments[1];
                    string parameterName = targetSegments[2];

                    container = this.Model.FindEntityContainer(containerName);
                    if (container != null)
                    {
                        IEdmOperationImport operationImport = FindParameterizedOperationImport(operationName, container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport);
                        if (operationImport != null)
                        {
                            // $ReturnType
                            if (parameterName == CsdlConstants.OperationReturnExternalTarget)
                            {
                                if (operationImport.Operation.ReturnType != null)
                                {
                                    return(operationImport.Operation.GetReturn());
                                }

                                return(new UnresolvedReturn(operationImport.Operation, this.Location));
                            }

                            IEdmOperationParameter parameter = operationImport.Operation.FindParameter(parameterName);
                            if (parameter != null)
                            {
                                return(parameter);
                            }

                            return(new UnresolvedParameter(operationImport.Operation, parameterName, this.Location));
                        }
                    }

                    string qualifiedOperationName           = containerName + "/" + operationName;
                    UnresolvedOperation unresolvedOperation = new UnresolvedOperation(qualifiedOperationName, Edm.Strings.Bad_UnresolvedOperation(qualifiedOperationName), this.Location);
                    if (parameterName == CsdlConstants.OperationReturnExternalTarget)
                    {
                        return(new UnresolvedReturn(unresolvedOperation, this.Location));
                    }
                    else
                    {
                        return(new UnresolvedParameter(unresolvedOperation, parameterName, this.Location));
                    }
                }

                return(new BadElement(new EdmError[] { new EdmError(this.Location, EdmErrorCode.ImpossibleAnnotationsTarget, Edm.Strings.CsdlSemantics_ImpossibleAnnotationsTarget(target)) }));
            }
        }
        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)
                    {
                        object result;
                        UriTemplateExpression expression;

                        if (enableUriTemplateParsing && UriTemplateParser.TryParseLiteral(lexer.CurrentToken.Text, functionParameter.Type, out expression))
                        {
                            result = expression;
                        }
                        else
                        {
                            // ExpressionTokenKind.BracketedExpression means text like [{\"Street\":\"NE 24th St.\",\"City\":\"Redmond\"},{\"Street\":\"Pine St.\",\"City\":\"Seattle\"}]
                            // so now try convert it into complex or collection type value:
                            result = ODataUriUtils.ConvertFromUriLiteral(valueStr, ODataVersion.V4, model, functionParameter.Type);
                        }

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

                partiallyParsedParametersWithComplexOrCollection.Add(funcParaToken);
            }

            return partiallyParsedParametersWithComplexOrCollection;
        }
        private IEdmVocabularyAnnotatable ComputeTarget()
        {
            if (this.targetContext != null)
            {
                return(this.targetContext);
            }
            else
            {
                Debug.Assert(this.annotationsContext != null, "Annotation must either have a target context or annotations context");
                string              target              = this.annotationsContext.Annotations.Target;
                string[]            targetSegments      = target.Split('/');
                int                 targetSegmentsCount = targetSegments.Count();
                IEdmEntityContainer container;

                if (targetSegmentsCount == 1)
                {
                    string         elementName = targetSegments[0];
                    IEdmSchemaType type        = this.schema.FindType(elementName);
                    if (type != null)
                    {
                        return(type);
                    }

                    IEdmValueTerm term = this.schema.FindValueTerm(elementName);
                    if (term != null)
                    {
                        return(term);
                    }

                    IEdmOperation operation = this.FindParameterizedOperation(elementName, this.Schema.FindOperations, this.CreateAmbiguousOperation);
                    if (operation != null)
                    {
                        return(operation);
                    }

                    container = this.schema.FindEntityContainer(elementName);
                    if (container != null)
                    {
                        return(container);
                    }

                    return(new UnresolvedType(this.Schema.UnresolvedName(targetSegments[0]), this.Location));
                }

                if (targetSegmentsCount == 2)
                {
                    container = this.schema.FindEntityContainer(targetSegments[0]);
                    if (container != null)
                    {
                        IEdmEntityContainerElement containerElement = container.FindEntitySetExtended(targetSegments[1]);
                        if (containerElement != null)
                        {
                            return(containerElement);
                        }

                        IEdmOperationImport operationImport = this.FindParameterizedOperationImport(targetSegments[1], container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport);
                        if (operationImport != null)
                        {
                            return(operationImport);
                        }

                        return(new UnresolvedEntitySet(targetSegments[1], container, this.Location));
                    }

                    IEdmStructuredType type = this.schema.FindType(targetSegments[0]) as IEdmStructuredType;
                    if (type != null)
                    {
                        IEdmProperty property = type.FindProperty(targetSegments[1]);
                        if (property != null)
                        {
                            return(property);
                        }

                        return(new UnresolvedProperty(type, targetSegments[1], this.Location));
                    }

                    IEdmOperation operation = this.FindParameterizedOperation(targetSegments[0], this.Schema.FindOperations, this.CreateAmbiguousOperation);
                    if (operation != null)
                    {
                        IEdmOperationParameter parameter = operation.FindParameter(targetSegments[1]);
                        if (parameter != null)
                        {
                            return(parameter);
                        }

                        return(new UnresolvedParameter(operation, targetSegments[1], this.Location));
                    }

                    return(new UnresolvedProperty(new UnresolvedEntityType(this.Schema.UnresolvedName(targetSegments[0]), this.Location), targetSegments[1], this.Location));
                }

                if (targetSegmentsCount == 3)
                {
                    // The only valid target with three segments is a function parameter.
                    string containerName = targetSegments[0];
                    string operationName = targetSegments[1];
                    string parameterName = targetSegments[2];

                    container = this.Model.FindEntityContainer(containerName);
                    if (container != null)
                    {
                        IEdmOperationImport operationImport = this.FindParameterizedOperationImport(operationName, container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport);
                        if (operationImport != null)
                        {
                            IEdmOperationParameter parameter = operationImport.Operation.FindParameter(parameterName);
                            if (parameter != null)
                            {
                                return(parameter);
                            }

                            return(new UnresolvedParameter(operationImport.Operation, parameterName, this.Location));
                        }
                    }

                    string qualifiedOperationName           = containerName + "/" + operationName;
                    UnresolvedOperation unresolvedOperation = new UnresolvedOperation(qualifiedOperationName, Edm.Strings.Bad_UnresolvedOperation(qualifiedOperationName), this.Location);
                    return(new UnresolvedParameter(unresolvedOperation, parameterName, this.Location));
                }

                return(new BadElement(new EdmError[] { new EdmError(this.Location, EdmErrorCode.ImpossibleAnnotationsTarget, Edm.Strings.CsdlSemantics_ImpossibleAnnotationsTarget(target)) }));
            }
        }
        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;
        }
        /// <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;
        }
Exemple #20
0
        public void CsdlTypeReferenceToStringTest()
        {
            const string csdl =
                @"<?xml version=""1.0"" encoding=""utf-16""?>
<Schema Namespace=""AwesomeNamespace"" Alias=""Alias"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
  <EntityType Name=""AstonishingEntity"">
    <Key>
      <PropertyRef Name=""Id"" />
    </Key>
    <Property Name=""Id"" Type=""Int32"" Nullable=""false"" />
  </EntityType>
  <EntityType Name=""AweInspiringEntity"">
    <Key>
      <PropertyRef Name=""Id"" />
    </Key>
    <Property Name=""Id"" Type=""Int32"" Nullable=""false"" />
    <Property Name=""AstonishingID"" Type=""Int32"" />
  </EntityType>
  <ComplexType Name=""BreathtakingComplex"">
    <Property Name=""Par1"" Type=""Int32"" Nullable=""false"" />
    <Property Name=""Par2"" Type=""Int32"" Nullable=""false"" />
  </ComplexType>
  <Function Name=""Function1""><ReturnType Type=""Edm.Int32""/>
    <Parameter Name=""P1"" Type=""AwesomeNamespace.AstonishingEntity"" />
    <Parameter Name=""P2"" Type=""AwesomeNamespace.BreathtakingComplex"" />
    <Parameter Name=""P3"" Type=""AwesomeNamespace.ExaltedAssociation"" />
    <Parameter Name=""P4"" Type=""Edm.Int32"" />
    <Parameter Name=""P5"" Type=""Edm.String"" MaxLength=""128"" Unicode=""false"" />
    <Parameter Name=""P6"" Type=""Edm.Stream"" />
    <Parameter Name=""P7"" Type=""Edm.Binary"" MaxLength=""max""/>
    <Parameter Name=""P8"" Type=""Edm.DateTimeOffset"" Precision=""1"" />
    <Parameter Name=""P9"" Type=""Edm.Decimal"" Precision=""3"" Scale=""2""/>
    <Parameter Name=""P10"" Type=""Edm.Geography"" SRID=""1""  />
    <Parameter Name=""P11"" Type=""Ref(AwesomeNamespace.AstonishingEntity)"" />
    <Parameter Name=""P12"" Type=""Collection(Edm.Int32)"" />
    <Parameter Name=""P14"" Type=""AwesomeNamespace.FabulousEnum"" />
  </Function>
  <EnumType Name=""FabulousEnum"">
    <Member Name=""m1"" />
    <Member Name=""m2"" />
  </EnumType>
</Schema>";
            IEdmModel model;
            IEnumerable <EdmError> errors;
            bool parsed = CsdlReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(csdl)) }, out model, out errors);

            Assert.IsTrue(parsed, "parsed");
            Assert.IsTrue(errors.Count() == 0, "No errors");

            IEdmOperation operation = (IEdmOperation)(model.FindOperations("AwesomeNamespace.Function1")).First();

            IEdmEntityTypeReference          entity      = operation.FindParameter("P1").Type.AsEntity();
            IEdmComplexTypeReference         complex     = operation.FindParameter("P2").Type.AsComplex();
            IEdmTypeReference                association = operation.FindParameter("P3").Type;
            IEdmPrimitiveTypeReference       primitive   = operation.FindParameter("P4").Type.AsPrimitive();
            IEdmStringTypeReference          stringType  = operation.FindParameter("P5").Type.AsString();
            IEdmPrimitiveTypeReference       stream      = operation.FindParameter("P6").Type.AsPrimitive();
            IEdmBinaryTypeReference          binary      = operation.FindParameter("P7").Type.AsBinary();
            IEdmTemporalTypeReference        temporal    = operation.FindParameter("P8").Type.AsTemporal();
            IEdmDecimalTypeReference         decimalType = operation.FindParameter("P9").Type.AsDecimal();
            IEdmSpatialTypeReference         spatial     = operation.FindParameter("P10").Type.AsSpatial();
            IEdmEntityReferenceTypeReference entityRef   = operation.FindParameter("P11").Type.AsEntityReference();
            IEdmCollectionTypeReference      collection  = operation.FindParameter("P12").Type.AsCollection();
            IEdmEnumTypeReference            enumTypeRef = operation.FindParameter("P14").Type.AsEnum();
            IEdmTypeReference                type        = operation.FindParameter("P1").Type;

            Assert.IsFalse(association.IsBad(), "Associations cannot be types");
            Assert.IsTrue(association.Definition.IsBad(), "Associations cannot be types");
            Assert.AreEqual("[AwesomeNamespace.AstonishingEntity Nullable=True]", entity.ToString(), "To string correct");
            Assert.AreEqual("[AwesomeNamespace.BreathtakingComplex Nullable=True]", complex.ToString(), "To string correct");
            Assert.AreEqual("[Edm.Int32 Nullable=True]", primitive.ToString(), "To string correct");
            Assert.AreEqual("[Edm.String Nullable=True MaxLength=128 Unicode=False]", stringType.ToString(), "To string correct");
            Assert.AreEqual("[Edm.Stream Nullable=True]", stream.ToString(), "To string correct");
            Assert.AreEqual("[Edm.Binary Nullable=True MaxLength=max]", binary.ToString(), "To string correct");
            Assert.AreEqual("[Edm.DateTimeOffset Nullable=True Precision=1]", temporal.ToString(), "To string correct");
            Assert.AreEqual("[Edm.Decimal Nullable=True Precision=3 Scale=2]", decimalType.ToString(), "To string correct");
            Assert.AreEqual("[Edm.Geography Nullable=True SRID=1]", spatial.ToString(), "To string correct");
            Assert.AreEqual("[Collection([Edm.Int32 Nullable=True]) Nullable=True]", collection.ToString(), "To string correct");
            Assert.AreEqual("[EntityReference(AwesomeNamespace.AstonishingEntity) Nullable=True]", entityRef.ToString(), "To string correct");
            Assert.AreEqual("[AwesomeNamespace.FabulousEnum Nullable=True]", enumTypeRef.ToString(), "To string correct");
            Assert.AreEqual("[AwesomeNamespace.AstonishingEntity Nullable=True]", type.ToString(), "To string correct");
        }