public void SingleModel_Annotation_OnEntityType() { const string applicationCsdl = @"<Schema Namespace=""bar"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Term Name=""MoreTransformedPersonTerm"" Type=""bar.MoreTransformedPerson"" /> <Annotations Target=""bar.Person""> <Annotation Term=""bar.MoreTransformedPersonTerm""> <Record> <PropertyValue Property=""Description"" String=""I know it!"" /> </Record> </Annotation> </Annotations> <EntityType Name=""MoreTransformedPerson"" BaseType=""bar.TransformedPerson""> <Property Name=""Description"" Type=""String"" /> </EntityType> <EntityType Name=""TransformedPerson""> <Property Name=""Age"" Type=""Int32"" Nullable=""false"" /> </EntityType> <EntityType Name=""Person""> <Key> <PropertyRef Name=""Name"" /> </Key> <Property Name=""Name"" Type=""String"" Nullable=""false"" /> </EntityType> </Schema>"; IEdmModel applicationModel = this.Parse(applicationCsdl); EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(null); var term = applicationModel.FindTerm("bar.MoreTransformedPersonTerm"); var property = applicationModel.FindEntityType("bar.MoreTransformedPerson").FindProperty("Description"); var fakeContextValue = new EdmStructuredValue(new EdmEntityTypeReference(applicationModel.FindEntityType("bar.Person"), true), Enumerable.Empty <IEdmPropertyValue>()); IEdmValue valueOfAnnotation = applicationModel.GetPropertyValue(fakeContextValue, term, property, expressionEvaluator); Assert.AreEqual("I know it!", ((IEdmStringValue)valueOfAnnotation).Value, "Annotation evaluated value."); }
public void EvaluateUnboundTerms() { const string applicationCsdl = @"<Schema Namespace=""bar"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Annotations Target=""bar.Person""> <Annotation Term=""bar.RandomTerm"" Path=""Extra"" /> </Annotations> <EntityType Name=""Person""> <Key> <PropertyRef Name=""Name"" /> </Key> <Property Name=""Name"" Type=""String"" Nullable=""false"" /> <Property Name=""Decoration"" Type=""bar.Decoration""> <Annotation Term=""bar.DecorationTerm"" Qualifier=""Goodness"" String=""Excellent"" /> </Property> </EntityType> <ComplexType Name=""Decoration""> <Property Name=""One"" Type=""Int32"" /> <Property Name=""Two"" Type=""Int32"" /> </ComplexType> </Schema>"; IEdmModel applicationModel = this.Parse(applicationCsdl); IEdmEntityType person = (IEdmEntityType)applicationModel.FindType("bar.Person"); IEdmProperty personDecoration = person.FindProperty("Decoration"); EdmToClrEvaluator evaluator = new EdmToClrEvaluator(null); List <IEdmPropertyValue> decorationPropertyValues = new List <IEdmPropertyValue>(); decorationPropertyValues.Add(new EdmPropertyValue("One", new EdmIntegerConstant(1))); decorationPropertyValues.Add(new EdmPropertyValue("Two", new EdmIntegerConstant(2))); List <IEdmPropertyValue> propertyValues = new List <IEdmPropertyValue>(); propertyValues.Add(new EdmPropertyValue("Name", new EdmStringConstant("Goober"))); propertyValues.Add(new EdmPropertyValue("Decoration", new EdmStructuredValue(null, decorationPropertyValues))); propertyValues.Add(new EdmPropertyValue("Extra", new EdmStringConstant("Extra value!"))); IEdmStructuredValue context = new EdmStructuredValue(new EdmEntityTypeReference(person, false), propertyValues); string random = applicationModel.GetTermValue <string>(context, "bar.RandomTerm", evaluator); Assert.AreEqual("Extra value!", random, "Annotation evaluated value."); IEdmValue randomValue = applicationModel.GetTermValue(context, "bar.RandomTerm", evaluator); Assert.AreEqual("Extra value!", ((IEdmStringValue)randomValue).Value, "Annotation evaluated value."); string goodness = applicationModel.GetTermValue <string>(personDecoration, "bar.DecorationTerm", "Goodness", evaluator); Assert.AreEqual("Excellent", goodness, "Annotation evaluated value."); IEdmValue goodnessValue = applicationModel.GetTermValue(personDecoration, "bar.DecorationTerm", "Goodness", evaluator); Assert.AreEqual("Excellent", ((IEdmStringValue)goodnessValue).Value, "Annotation evaluated value."); IEdmVocabularyAnnotation randomTermAnnotation = applicationModel.FindVocabularyAnnotations <IEdmVocabularyAnnotation>(person, "bar.RandomTerm").Single(); random = evaluator.EvaluateToClrValue <string>(randomTermAnnotation.Value, context); Assert.AreEqual("Extra value!", random, "Annotation evaluated value."); }
private void SetupValues() { IEdmEntityType person = (IEdmEntityType)this.baseModel.FindType("foo.Person"); IEdmEntityType professional = (IEdmEntityType)this.baseModel.FindType("foo.Professional"); IEdmEntityType address = (IEdmEntityType)this.baseModel.FindType("foo.Address"); // ?? no EdmComplexValue var zipMain = new EdmPropertyValue("Main", new EdmStringConstant("98052")); var zipExtension = new EdmPropertyValue("Extension", new EdmStringConstant("0000")); var zipValue = new EdmPropertyValue("Zip", new EdmStructuredValue(null, new EdmPropertyValue[] { zipMain, zipExtension })); EdmPropertyValue address1Number = new EdmPropertyValue("Number", new EdmIntegerConstant(null, 1)); EdmPropertyValue address1Street = new EdmPropertyValue("Street", new EdmStringConstant(null, "Joey Ramone Place")); EdmPropertyValue address1City = new EdmPropertyValue("City", new EdmStringConstant(null, "New York")); EdmPropertyValue address1State = new EdmPropertyValue("State", new EdmStringConstant(null, "New York")); EdmPropertyValue[] address1Properties = new EdmPropertyValue[] { address1Number, address1Street, address1City, address1State, zipValue }; EdmStructuredValue address1Value = new EdmStructuredValue(new EdmEntityTypeReference(address, true), address1Properties); var phoneLocal = new EdmPropertyValue("Local", new EdmIntegerConstant(9991234)); var phoneValue = new EdmPropertyValue("WorkPhone", new EdmStructuredValue(null, new EdmPropertyValue[] { phoneLocal })); var contactInfoValue = new EdmPropertyValue("ContactInfo", new EdmStructuredValue(null, new EdmPropertyValue[] { phoneValue })); EdmPropertyValue person1Name = new EdmPropertyValue("Name", new EdmStringConstant(null, "Joey Ramone")); EdmPropertyValue person1Birthday = new EdmPropertyValue("Birthday", new EdmDateTimeOffsetConstant(null, new DateTimeOffset(1951, 5, 19, 0, 0, 0, TimeSpan.Zero))); EdmPropertyValue person1CoolnessIndex = new EdmPropertyValue("CoolnessIndex", new EdmIntegerConstant(null, Int32.MaxValue)); EdmPropertyValue person1Living = new EdmPropertyValue("Living", new EdmBooleanConstant(false)); EdmPropertyValue person1Famous = new EdmPropertyValue("Famous", new EdmBooleanConstant(null, true)); EdmPropertyValue person1Address = new EdmPropertyValue("Address", address1Value); EdmPropertyValue[] person1Properties = new EdmPropertyValue[] { person1Name, person1Birthday, person1CoolnessIndex, person1Living, person1Famous, person1Address, contactInfoValue }; this.personValue = new EdmStructuredValue(new EdmEntityTypeReference(person, false), person1Properties); this.professionalValue = new EdmStructuredValue(new EdmEntityTypeReference(professional, false), person1Properties); }
public void ClrTypeMappingValueAnnotationRecordValueTypeTest() { var csdls = new List <XElement>(); csdls.Add(XElement.Parse( @"<Schema Namespace='NS1' xmlns='http://docs.oasis-open.org/odata/ns/edm'> <EntityType Name='Person'> <Property Name='Id' Type='Int16' Nullable='false' /> <Property Name='FirstName' Type='String' Nullable='false' Unicode='true' /> <Property Name='LastName' Type='String' Nullable='false' Unicode='true' /> </EntityType> <EntityType Name='DifferentPerson'> <Property Name='Id' Type='Int16' Nullable='false' /> <Property Name='FirstName' Type='String' Nullable='false' Unicode='true' /> <Property Name='LastName' Type='String' Nullable='false' Unicode='true' /> </EntityType> <Term Name='InspectedBy' Type='NS1.DifferentPerson' Nullable='false' /> <Annotations Target='NS1.Person'> <Annotation Term=""NS1.InspectedBy""> <Record> <PropertyValue Property=""Id"" Int=""10"" /> <PropertyValue Property=""FirstName""> <String>Young</String> </PropertyValue> <PropertyValue Property=""LastName"" String='Hong'> </PropertyValue> </Record> </Annotation> </Annotations> </Schema>" )); var edmModel = this.GetParserResult(csdls); var person = edmModel.FindEntityType("NS1.Person"); var differentPerson = edmModel.FindEntityType("NS1.DifferentPerson"); EdmStructuredValue dummyPerson = new EdmStructuredValue( new EdmEntityTypeReference(person, false), new EdmPropertyValue[3] { new EdmPropertyValue("Id", new EdmIntegerConstant(-1)), new EdmPropertyValue("FirstName", new EdmStringConstant("Noman")), new EdmPropertyValue("LastName", new EdmStringConstant("Nobody")) }); var edmValue = edmModel.GetTermValue(dummyPerson, "NS1.InspectedBy", new EdmToClrEvaluator(null)); Assert.AreEqual(edmValue.Type.Definition, differentPerson, "The InspectedBy annotation's type should be same as type defined in the term."); }
//[TestMethod, Variation(Id = 202, SkipReason = @"[EdmLib] Evaluator extension method assumes value is always EntityValue -- postponed")] public void GetTermValueWithNonEntityTest() { const string annotatingModelCsdl = @"<Schema Namespace=""foo"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Term Name=""DistantAge"" Type=""Int32"" /> </Schema>"; var aValue = new EdmStructuredValue(null, new IEdmPropertyValue[] { new EdmPropertyValue("P1", new EdmStringConstant("aStringValueOne")), new EdmPropertyValue("P2", new EdmStringConstant("aStringValueTwo")), }); var edmModel = this.GetParserResult(new XElement[] { XElement.Parse(annotatingModelCsdl) }); var evaluator = new EdmExpressionEvaluator(null); edmModel.GetTermValue(aValue, edmModel.FindTerm("foo.DistantAge"), evaluator); }
public void TestElementInterfaceCriticalEnumerableMustNotHaveNullElements() { var expectedErrors = new EdmLibTestErrors() { { null, null, EdmErrorCode.InterfaceCriticalEnumerableMustNotHaveNullElements } }; EdmPropertyValue personName = new EdmPropertyValue("Name", new EdmStringConstant("foo")); EdmPropertyValue[] properties = new EdmPropertyValue[] { personName, null }; var structuralValue = new EdmStructuredValue(new EdmEntityTypeReference(new EdmEntityType("", ""), false), properties); var actualErrors = structuralValue.Errors(); Assert.IsTrue(structuralValue.IsBad(), "Element is expected to be bad."); this.CompareErrors(actualErrors, expectedErrors); }
private static void RunPinningTest(StringBuilder builder, params object[] keyValues) { var compositeKey = keyValues.Select((k, i) => new { Name = "prop" + i, Value = k }).ToArray(); var allKeys = keyValues.Select(k => new[] { new { Name = "prop", Value = k } }).Concat(new[] { compositeKey }); foreach (var key in allKeys) { if (builder.Length > 0) { builder.AppendLine(); } var properties = key.Select(p => new EdmPropertyValue(p.Name, EdmValueUtils.ConvertPrimitiveValue(p.Value, null).Value)).ToList(); var entityType = new EdmEntityType("Fake", "Fake"); entityType.AddKeys(properties.Select(p => new EdmStructuralProperty(entityType, p.Name, p.Value.Type))); var entity = new EdmStructuredValue(new EdmEntityTypeReference(entityType, false), properties); ODataConventionalUriBuilder uriBuilder = new ODataConventionalUriBuilder(new Uri("http://baseuri.org/"), UrlConvention.CreateWithExplicitValue(false)); var entityInstanceUri = uriBuilder.BuildEntityInstanceUri(new Uri("http://baseuri.org/Customers"), new Collection <KeyValuePair <string, object> >(properties.Select(p => new KeyValuePair <string, object>(p.Name, ((IEdmPrimitiveValue)p.Value).ToClrValue())).ToList()), entity.Type.FullName()); builder.Append(entityInstanceUri.OriginalString.Replace("http://baseuri.org/Customers", null).Replace("()", "%28%29")); } builder.AppendLine(); }
private IEdmValue Eval(IEdmExpression expression, IEdmStructuredValue context) { switch (expression.ExpressionKind) { case EdmExpressionKind.IntegerConstant: return((IEdmIntegerConstantExpression)expression); case EdmExpressionKind.StringConstant: return((IEdmStringConstantExpression)expression); case EdmExpressionKind.BinaryConstant: return((IEdmBinaryConstantExpression)expression); case EdmExpressionKind.BooleanConstant: return((IEdmBooleanConstantExpression)expression); case EdmExpressionKind.DateTimeConstant: return((IEdmDateTimeConstantExpression)expression); case EdmExpressionKind.DateTimeOffsetConstant: return((IEdmDateTimeOffsetConstantExpression)expression); case EdmExpressionKind.DecimalConstant: return((IEdmDecimalConstantExpression)expression); case EdmExpressionKind.FloatingConstant: return((IEdmFloatingConstantExpression)expression); case EdmExpressionKind.GuidConstant: return((IEdmGuidConstantExpression)expression); case EdmExpressionKind.TimeConstant: return((IEdmTimeConstantExpression)expression); case EdmExpressionKind.Null: return((IEdmNullExpression)expression); case EdmExpressionKind.Path: { EdmUtil.CheckArgumentNull(context, "context"); IEdmPathExpression pathExpression = (IEdmPathExpression)expression; IEdmValue result = context; foreach (string hop in pathExpression.Path) { result = this.FindProperty(hop, result); if (result == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundPath(hop)); } } return(result); } case EdmExpressionKind.FunctionApplication: { IEdmApplyExpression apply = (IEdmApplyExpression)expression; IEdmExpression targetReference = apply.AppliedFunction; IEdmFunctionReferenceExpression targetFunctionReference = targetReference as IEdmFunctionReferenceExpression; if (targetFunctionReference != null) { IList <IEdmExpression> argumentExpressions = apply.Arguments.ToList(); IEdmValue[] arguments = new IEdmValue[argumentExpressions.Count()]; { int argumentIndex = 0; foreach (IEdmExpression argument in argumentExpressions) { arguments[argumentIndex++] = this.Eval(argument, context); } } IEdmFunction target = targetFunctionReference.ReferencedFunction; if (!target.IsBad()) { //// Static validation will have checked that the number and types of arguments are correct, //// so those checks are not performed dynamically. Func <IEdmValue[], IEdmValue> functionEvaluator; if (this.builtInFunctions.TryGetValue(target, out functionEvaluator)) { return(functionEvaluator(arguments)); } } if (this.lastChanceFunctionApplier != null) { return(this.lastChanceFunctionApplier(target.FullName(), arguments)); } } throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundFunction(targetFunctionReference != null ? targetFunctionReference.ReferencedFunction.ToTraceString() : string.Empty)); } case EdmExpressionKind.If: { IEdmIfExpression ifExpression = (IEdmIfExpression)expression; if (((IEdmBooleanValue)this.Eval(ifExpression.TestExpression, context)).Value) { return(this.Eval(ifExpression.TrueExpression, context)); } return(this.Eval(ifExpression.FalseExpression, context)); } case EdmExpressionKind.IsType: { IEdmIsTypeExpression isType = (IEdmIsTypeExpression)expression; IEdmValue operand = this.Eval(isType.Operand, context); IEdmTypeReference targetType = isType.Type; return(new EdmBooleanConstant(MatchesType(targetType, operand))); } case EdmExpressionKind.AssertType: { IEdmAssertTypeExpression assertType = (IEdmAssertTypeExpression)expression; IEdmValue operand = this.Eval(assertType.Operand, context); IEdmTypeReference targetType = assertType.Type; return(AssertType(targetType, operand)); } case EdmExpressionKind.Record: { IEdmRecordExpression record = (IEdmRecordExpression)expression; DelayedExpressionContext recordContext = new DelayedExpressionContext(this, context); List <IEdmPropertyValue> propertyValues = new List <IEdmPropertyValue>(); //// Static validation will have checked that the set of supplied properties are appropriate //// for the supplied type and have no duplicates, so those checks are not performed dynamically. foreach (IEdmPropertyConstructor propertyConstructor in record.Properties) { propertyValues.Add(new DelayedRecordProperty(recordContext, propertyConstructor)); } EdmStructuredValue result = new EdmStructuredValue(record.DeclaredType != null ? record.DeclaredType.AsStructured() : null, propertyValues); return(result); } case EdmExpressionKind.Collection: { IEdmCollectionExpression collection = (IEdmCollectionExpression)expression; DelayedExpressionContext collectionContext = new DelayedExpressionContext(this, context); List <IEdmDelayedValue> elementValues = new List <IEdmDelayedValue>(); //// Static validation will have checked that the result types of the element expressions are //// appropriate and so these checks are not performed dynamically. foreach (IEdmExpression element in collection.Elements) { elementValues.Add(this.MapLabeledExpressionToDelayedValue(element, collectionContext, context)); } EdmCollectionValue result = new EdmCollectionValue(collection.DeclaredType != null ? collection.DeclaredType.AsCollection() : null, elementValues); return(result); } case EdmExpressionKind.LabeledExpressionReference: { return(this.MapLabeledExpressionToDelayedValue(((IEdmLabeledExpressionReferenceExpression)expression).ReferencedLabeledExpression, null, context).Value); } case EdmExpressionKind.Labeled: return(this.MapLabeledExpressionToDelayedValue(expression, new DelayedExpressionContext(this, context), context).Value); case EdmExpressionKind.ParameterReference: case EdmExpressionKind.FunctionReference: case EdmExpressionKind.PropertyReference: case EdmExpressionKind.ValueTermReference: case EdmExpressionKind.EntitySetReference: case EdmExpressionKind.EnumMemberReference: throw new InvalidOperationException("Not yet implemented: evaluation of " + expression.ExpressionKind.ToString() + " expressions."); default: throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnrecognizedExpressionKind(((int)expression.ExpressionKind).ToString(System.Globalization.CultureInfo.InvariantCulture))); } }
public void TestStructuredValue() { var constant = new EdmStructuredValue(null, new List <IEdmPropertyValue>()); Assert.AreEqual(EdmValueKind.Structured, constant.ValueKind, "Invalid value kind."); }
private IEdmValue Eval(IEdmExpression expression, IEdmStructuredValue context) { switch (expression.ExpressionKind) { case EdmExpressionKind.IntegerConstant: return((IEdmIntegerConstantExpression)expression); case EdmExpressionKind.StringConstant: return((IEdmStringConstantExpression)expression); case EdmExpressionKind.BinaryConstant: return((IEdmBinaryConstantExpression)expression); case EdmExpressionKind.BooleanConstant: return((IEdmBooleanConstantExpression)expression); case EdmExpressionKind.DateTimeOffsetConstant: return((IEdmDateTimeOffsetConstantExpression)expression); case EdmExpressionKind.DecimalConstant: return((IEdmDecimalConstantExpression)expression); case EdmExpressionKind.FloatingConstant: return((IEdmFloatingConstantExpression)expression); case EdmExpressionKind.GuidConstant: return((IEdmGuidConstantExpression)expression); case EdmExpressionKind.DurationConstant: return((IEdmDurationConstantExpression)expression); case EdmExpressionKind.DateConstant: return((IEdmDateConstantExpression)expression); case EdmExpressionKind.TimeOfDayConstant: return((IEdmTimeOfDayConstantExpression)expression); case EdmExpressionKind.Null: return((IEdmNullExpression)expression); case EdmExpressionKind.Path: { if (context == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_NoContextPath); } IEdmPathExpression pathExpression = (IEdmPathExpression)expression; IEdmValue result = context; #if ORCAS // [EdmLib] Need to handle paths that bind to things other than properties. foreach (string hop in pathExpression.Path) { result = FindProperty(hop, result); if (result == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundPath(hop)); } } #else // Only Support Annotation in EntityType or ComplexType or Property or NavigationProperty. // Empty Path is not supported. foreach (string hop in pathExpression.Path) { if (hop.Contains("@")) { var currentPathSegementInfos = hop.Split('@'); var propertyName = currentPathSegementInfos[0]; var termInfo = currentPathSegementInfos[1]; IEdmExpression termCastExpression = null; if (!string.IsNullOrWhiteSpace(termInfo)) { var termInfos = termInfo.Split('#'); if (termInfos.Length <= 2) { string termName = termInfos[0]; string qualifier = termInfos.Length == 2 ? termInfos[1] : null; if (string.IsNullOrWhiteSpace(propertyName) && this.getAnnotationExpressionForType != null) { termCastExpression = this.getAnnotationExpressionForType(edmModel, context.Type.Definition, termName, qualifier); } else if (!string.IsNullOrWhiteSpace(propertyName) && this.getAnnotationExpressionForProperty != null) { termCastExpression = this.getAnnotationExpressionForProperty(edmModel, context.Type.Definition, propertyName, termName, qualifier); } } } if (termCastExpression == null) { result = null; break; } result = this.Eval(termCastExpression, context); } else if (hop == "$count") { var edmCollectionValue = result as IEdmCollectionValue; if (edmCollectionValue != null) { result = new EdmIntegerConstant(edmCollectionValue.Elements.Count()); } else { result = null; break; } } else if (hop.Contains(".")) { if (edmModel == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_TypeCastNeedsEdmModel); } IEdmType typeSegmentClientType = this.resolveTypeFromName(hop, this.edmModel); if (typeSegmentClientType == null) { result = null; break; } IEdmTypeReference operandType = result.Type; EdmValueKind operandKind = result.ValueKind; if (operandKind == EdmValueKind.Collection) { List <IEdmDelayedValue> elementValues = new List <IEdmDelayedValue>(); var collection = result as IEdmCollectionValue; foreach (IEdmDelayedValue element in collection.Elements) { if (element.Value.Type.Definition.IsOrInheritsFrom(typeSegmentClientType)) { elementValues.Add(element); } } result = new EdmCollectionValue( new EdmCollectionTypeReference(new EdmCollectionType(typeSegmentClientType.GetTypeReference(false))), elementValues); } else if (operandKind != EdmValueKind.Structured || (operandKind == EdmValueKind.Structured && !operandType.Definition.IsOrInheritsFrom(typeSegmentClientType))) { result = null; break; } } else { result = FindProperty(hop, result); if (result == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundPath(hop)); } } } #endif return(result); } case EdmExpressionKind.PropertyPath: case EdmExpressionKind.NavigationPropertyPath: { EdmUtil.CheckArgumentNull(context, "context"); IEdmPathExpression pathExpression = (IEdmPathExpression)expression; IEdmValue result = context; // [EdmLib] Need to handle paths that bind to things other than properties. foreach (string hop in pathExpression.Path) { result = FindProperty(hop, result); if (result == null) { throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundPath(hop)); } } return(result); } case EdmExpressionKind.OperationApplication: { IEdmApplyExpression apply = (IEdmApplyExpression)expression; IEdmExpression targetReference = apply.AppliedOperation; IEdmOperationReferenceExpression targetOperationReference = targetReference as IEdmOperationReferenceExpression; if (targetOperationReference != null) { IList <IEdmExpression> argumentExpressions = apply.Arguments.ToList(); IEdmValue[] arguments = new IEdmValue[argumentExpressions.Count()]; { int argumentIndex = 0; foreach (IEdmExpression argument in argumentExpressions) { arguments[argumentIndex++] = this.Eval(argument, context); } } IEdmOperation target = targetOperationReference.ReferencedOperation; //// Static validation will have checked that the number and types of arguments are correct, //// so those checks are not performed dynamically. Func <IEdmValue[], IEdmValue> operationEvaluator; if (this.builtInFunctions.TryGetValue(target, out operationEvaluator)) { return(operationEvaluator(arguments)); } if (this.lastChanceOperationApplier != null) { return(this.lastChanceOperationApplier(target.FullName(), arguments)); } } throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnboundFunction(targetOperationReference != null ? targetOperationReference.ReferencedOperation.ToTraceString() : string.Empty)); } case EdmExpressionKind.If: { IEdmIfExpression ifExpression = (IEdmIfExpression)expression; if (((IEdmBooleanValue)this.Eval(ifExpression.TestExpression, context)).Value) { return(this.Eval(ifExpression.TrueExpression, context)); } return(this.Eval(ifExpression.FalseExpression, context)); } case EdmExpressionKind.IsType: { IEdmIsTypeExpression isType = (IEdmIsTypeExpression)expression; IEdmValue operand = this.Eval(isType.Operand, context); IEdmTypeReference targetType = isType.Type; return(new EdmBooleanConstant(MatchesType(targetType, operand))); } case EdmExpressionKind.Cast: { IEdmCastExpression castType = (IEdmCastExpression)expression; IEdmValue operand = this.Eval(castType.Operand, context); IEdmTypeReference targetType = castType.Type; return(Cast(targetType, operand)); } case EdmExpressionKind.Record: { IEdmRecordExpression record = (IEdmRecordExpression)expression; DelayedExpressionContext recordContext = new DelayedExpressionContext(this, context); List <IEdmPropertyValue> propertyValues = new List <IEdmPropertyValue>(); //// Static validation will have checked that the set of supplied properties are appropriate //// for the supplied type and have no duplicates, so those checks are not performed dynamically. foreach (IEdmPropertyConstructor propertyConstructor in record.Properties) { propertyValues.Add(new DelayedRecordProperty(recordContext, propertyConstructor)); } EdmStructuredValue result = new EdmStructuredValue(record.DeclaredType != null ? record.DeclaredType.AsStructured() : null, propertyValues); return(result); } case EdmExpressionKind.Collection: { IEdmCollectionExpression collection = (IEdmCollectionExpression)expression; DelayedExpressionContext collectionContext = new DelayedExpressionContext(this, context); List <IEdmDelayedValue> elementValues = new List <IEdmDelayedValue>(); //// Static validation will have checked that the result types of the element expressions are //// appropriate and so these checks are not performed dynamically. foreach (IEdmExpression element in collection.Elements) { elementValues.Add(this.MapLabeledExpressionToDelayedValue(element, collectionContext, context)); } EdmCollectionValue result = new EdmCollectionValue(collection.DeclaredType != null ? collection.DeclaredType.AsCollection() : null, elementValues); return(result); } case EdmExpressionKind.LabeledExpressionReference: { return(this.MapLabeledExpressionToDelayedValue(((IEdmLabeledExpressionReferenceExpression)expression).ReferencedLabeledExpression, null, context).Value); } case EdmExpressionKind.Labeled: return(this.MapLabeledExpressionToDelayedValue(expression, new DelayedExpressionContext(this, context), context).Value); case EdmExpressionKind.EnumMember: IEdmEnumMemberExpression enumMemberExpression = (IEdmEnumMemberExpression)expression; var enumMembers = enumMemberExpression.EnumMembers.ToList(); IEdmEnumType enumType = enumMembers.First().DeclaringType; IEdmEnumTypeReference enumTypeReference = new EdmEnumTypeReference(enumType, false); if (enumMembers.Count() == 1) { return(new EdmEnumValue(enumTypeReference, enumMemberExpression.EnumMembers.Single())); } else { if (!enumType.IsFlags || !EdmEnumValueParser.IsEnumIntergeType(enumType)) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Type {0} cannot be assigned with multi-values.", enumType.FullName())); } long result = 0; foreach (var enumMember in enumMembers) { long value = (enumMember.Value as EdmIntegerConstant).Value; result |= value; } return(new EdmEnumValue(enumTypeReference, new EdmIntegerConstant(result))); } case EdmExpressionKind.EnumMemberReference: IEdmEnumMemberReferenceExpression enumMemberReferenceExpression = (IEdmEnumMemberReferenceExpression)expression; var referencedEnumMember = enumMemberReferenceExpression.ReferencedEnumMember; IEdmEnumTypeReference referencedEnumTypeReference = new EdmEnumTypeReference(referencedEnumMember.DeclaringType, false); return(new EdmEnumValue(referencedEnumTypeReference, enumMemberReferenceExpression.ReferencedEnumMember)); case EdmExpressionKind.ParameterReference: case EdmExpressionKind.OperationReference: case EdmExpressionKind.PropertyReference: case EdmExpressionKind.ValueTermReference: case EdmExpressionKind.EntitySetReference: throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnrecognizedExpressionKind(((int)expression.ExpressionKind).ToString(System.Globalization.CultureInfo.InvariantCulture))); default: throw new InvalidOperationException(Edm.Strings.Edm_Evaluator_UnrecognizedExpressionKind(((int)expression.ExpressionKind).ToString(System.Globalization.CultureInfo.InvariantCulture))); } }
private IEdmValue Eval(IEdmExpression expression, IEdmStructuredValue context) { Func <IEdmValue[], IEdmValue> func = null; IEdmStructuredTypeReference edmStructuredTypeReference; IEdmCollectionTypeReference edmCollectionTypeReference; object traceString; EdmExpressionKind expressionKind = expression.ExpressionKind; switch (expressionKind) { case EdmExpressionKind.BinaryConstant: { return((IEdmBinaryConstantExpression)expression); } case EdmExpressionKind.BooleanConstant: { return((IEdmBooleanConstantExpression)expression); } case EdmExpressionKind.DateTimeConstant: { return((IEdmDateTimeConstantExpression)expression); } case EdmExpressionKind.DateTimeOffsetConstant: { return((IEdmDateTimeOffsetConstantExpression)expression); } case EdmExpressionKind.DecimalConstant: { return((IEdmDecimalConstantExpression)expression); } case EdmExpressionKind.FloatingConstant: { return((IEdmFloatingConstantExpression)expression); } case EdmExpressionKind.GuidConstant: { return((IEdmGuidConstantExpression)expression); } case EdmExpressionKind.IntegerConstant: { return((IEdmIntegerConstantExpression)expression); } case EdmExpressionKind.StringConstant: { return((IEdmStringConstantExpression)expression); } case EdmExpressionKind.TimeConstant: { return((IEdmTimeConstantExpression)expression); } case EdmExpressionKind.Null: { return((IEdmNullExpression)expression); } case EdmExpressionKind.Record: { IEdmRecordExpression edmRecordExpression = (IEdmRecordExpression)expression; EdmExpressionEvaluator.DelayedExpressionContext delayedExpressionContext = new EdmExpressionEvaluator.DelayedExpressionContext(this, context); List <IEdmPropertyValue> edmPropertyValues = new List <IEdmPropertyValue>(); foreach (IEdmPropertyConstructor property in edmRecordExpression.Properties) { edmPropertyValues.Add(new EdmExpressionEvaluator.DelayedRecordProperty(delayedExpressionContext, property)); } if (edmRecordExpression.DeclaredType != null) { edmStructuredTypeReference = edmRecordExpression.DeclaredType.AsStructured(); } else { edmStructuredTypeReference = null; } EdmStructuredValue edmStructuredValue = new EdmStructuredValue(edmStructuredTypeReference, edmPropertyValues); return(edmStructuredValue); } case EdmExpressionKind.Collection: { IEdmCollectionExpression edmCollectionExpression = (IEdmCollectionExpression)expression; EdmExpressionEvaluator.DelayedExpressionContext delayedExpressionContext1 = new EdmExpressionEvaluator.DelayedExpressionContext(this, context); List <IEdmDelayedValue> edmDelayedValues = new List <IEdmDelayedValue>(); foreach (IEdmExpression element in edmCollectionExpression.Elements) { edmDelayedValues.Add(this.MapLabeledExpressionToDelayedValue(element, delayedExpressionContext1, context)); } if (edmCollectionExpression.DeclaredType != null) { edmCollectionTypeReference = edmCollectionExpression.DeclaredType.AsCollection(); } else { edmCollectionTypeReference = null; } EdmCollectionValue edmCollectionValue = new EdmCollectionValue(edmCollectionTypeReference, edmDelayedValues); return(edmCollectionValue); } case EdmExpressionKind.Path: { EdmUtil.CheckArgumentNull <IEdmStructuredValue>(context, "context"); IEdmPathExpression edmPathExpression = (IEdmPathExpression)expression; IEdmValue edmValue = context; foreach (string path in edmPathExpression.Path) { edmValue = this.FindProperty(path, edmValue); if (edmValue != null) { continue; } throw new InvalidOperationException(Strings.Edm_Evaluator_UnboundPath(path)); } return(edmValue); } case EdmExpressionKind.ParameterReference: case EdmExpressionKind.FunctionReference: case EdmExpressionKind.PropertyReference: case EdmExpressionKind.ValueTermReference: case EdmExpressionKind.EntitySetReference: case EdmExpressionKind.EnumMemberReference: { throw new InvalidOperationException(string.Concat("Not yet implemented: evaluation of ", expression.ExpressionKind.ToString(), " expressions.")); } case EdmExpressionKind.If: { IEdmIfExpression edmIfExpression = (IEdmIfExpression)expression; if (!((IEdmBooleanValue)this.Eval(edmIfExpression.TestExpression, context)).Value) { return(this.Eval(edmIfExpression.FalseExpression, context)); } else { return(this.Eval(edmIfExpression.TrueExpression, context)); } } case EdmExpressionKind.AssertType: { IEdmAssertTypeExpression edmAssertTypeExpression = (IEdmAssertTypeExpression)expression; IEdmValue edmValue1 = this.Eval(edmAssertTypeExpression.Operand, context); IEdmTypeReference type = edmAssertTypeExpression.Type; return(EdmExpressionEvaluator.AssertType(type, edmValue1)); } case EdmExpressionKind.IsType: { IEdmIsTypeExpression edmIsTypeExpression = (IEdmIsTypeExpression)expression; IEdmValue edmValue2 = this.Eval(edmIsTypeExpression.Operand, context); IEdmTypeReference edmTypeReference = edmIsTypeExpression.Type; return(new EdmBooleanConstant(EdmExpressionEvaluator.MatchesType(edmTypeReference, edmValue2))); } case EdmExpressionKind.FunctionApplication: { IEdmApplyExpression edmApplyExpression = (IEdmApplyExpression)expression; IEdmExpression appliedFunction = edmApplyExpression.AppliedFunction; IEdmFunctionReferenceExpression edmFunctionReferenceExpression = appliedFunction as IEdmFunctionReferenceExpression; if (edmFunctionReferenceExpression != null) { IList <IEdmExpression> list = edmApplyExpression.Arguments.ToList <IEdmExpression>(); IEdmValue[] edmValueArray = new IEdmValue[list.Count <IEdmExpression>()]; int num = 0; foreach (IEdmExpression edmExpression in list) { int num1 = num; num = num1 + 1; edmValueArray[num1] = this.Eval(edmExpression, context); } IEdmFunction referencedFunction = edmFunctionReferenceExpression.ReferencedFunction; if (referencedFunction.IsBad() || !this.builtInFunctions.TryGetValue(referencedFunction, out func)) { if (this.lastChanceFunctionApplier != null) { return(this.lastChanceFunctionApplier(referencedFunction.FullName(), edmValueArray)); } } else { return(func(edmValueArray)); } } if (edmFunctionReferenceExpression != null) { traceString = edmFunctionReferenceExpression.ReferencedFunction.ToTraceString(); } else { traceString = string.Empty; } throw new InvalidOperationException(Strings.Edm_Evaluator_UnboundFunction(traceString)); } case EdmExpressionKind.LabeledExpressionReference: { return(this.MapLabeledExpressionToDelayedValue(((IEdmLabeledExpressionReferenceExpression)expression).ReferencedLabeledExpression, null, context).Value); } case EdmExpressionKind.Labeled: { return(this.MapLabeledExpressionToDelayedValue(expression, new EdmExpressionEvaluator.DelayedExpressionContext(this, context), context).Value); } } int expressionKind1 = (int)expression.ExpressionKind; throw new InvalidOperationException(Strings.Edm_Evaluator_UnrecognizedExpressionKind(expressionKind1.ToString(CultureInfo.InvariantCulture))); }