public void ValueTerm_Path_OnProperty() { this.SetupModelsAndValues(); const string applicationCsdl = @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Annotations Target=""foo.Person/ContactInfo""> <Annotation Term=""bar.Int16Value"" Qualifier=""WorkPhoneLocal"" Path=""WorkPhone/Local"" /> </Annotations> </Schema>"; IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel); EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup); IEdmEntityType person = this.baseModel.FindEntityType("foo.Person"); IEdmProperty property = person.FindProperty("ContactInfo"); IEdmPropertyValue contextPropertyValue = ((IEdmStructuredValue)this.personValue).FindPropertyValue("ContactInfo"); IEdmValueTerm termInt16Value = this.vocabularyDefinitionModel.FindValueTerm("bar.Int16Value"); // ?? Assumes Entity always?? // IEdmValue annotationHotIndex = applicationModel.GetTermValue(contextPropertyValue.Value, termInt16Value, evaluator); IEdmValueAnnotation annotation = property.VocabularyAnnotations(applicationModel).SingleOrDefault(a => a.Term == termInt16Value) as IEdmValueAnnotation; IEdmExpression expression = annotation.Value; IEdmValue annotationWorkphoneLocal = expressionEvaluator.Evaluate(expression, (IEdmStructuredValue)contextPropertyValue.Value); Assert.AreEqual(9991234, ((IEdmIntegerValue)annotationWorkphoneLocal).Value, "Term annotation value"); }
public void EnumPropertyWithConcurrencyToken_SetsVocabuaryAnnotaion() { // Arrange var builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>().Add_Color_EnumType(); var entityTypeConfiguration = builder.EntityType <EntityTypeWithEnumTypePropertyTestModel>(); entityTypeConfiguration.EnumProperty(c => c.RequiredColor).IsOptional().IsConcurrencyToken(); builder.EntitySet <EntityTypeWithEnumTypePropertyTestModel>("EnumEntities"); // Act var model = builder.GetEdmModel(); // Assert var entityset = model.FindDeclaredEntitySet("EnumEntities"); Assert.NotNull(entityset); var annotations = model.FindVocabularyAnnotations <IEdmValueAnnotation>(entityset, CoreVocabularyModel.ConcurrencyTerm); IEdmValueAnnotation concurrencyAnnotation = Assert.Single(annotations); IEdmCollectionExpression properties = concurrencyAnnotation.Value as IEdmCollectionExpression; Assert.NotNull(properties); Assert.Equal(1, properties.Elements.Count()); var element = properties.Elements.First() as IEdmPathExpression; Assert.NotNull(element); string path = Assert.Single(element.Path); Assert.Equal("RequiredColor", path); }
public void ValueTerm_OperationApplication_OnNavigationProperty() { this.SetupModelsAndValues(); const string applicationCsdl = @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Annotations Target=""foo.Person/Address""> <Annotation Term=""bar.StringValue""> <Apply Function=""Functions.StringConcat""> <Path>Zip/Main</Path> <Apply Function=""Functions.StringConcat""> <String>-</String> <Path>Zip/Extension</Path> </Apply> </Apply> </Annotation> </Annotations> </Schema>"; IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel, this.operationsModel); EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup); IEdmEntityType person = this.baseModel.FindEntityType("foo.Person"); IEdmProperty property = person.FindProperty("Address"); IEdmPropertyValue contextPropertyValue = ((IEdmStructuredValue)this.personValue).FindPropertyValue("Address"); IEdmValueTerm termStringValue = this.vocabularyDefinitionModel.FindValueTerm("bar.StringValue"); IEdmValueAnnotation annotationString = property.VocabularyAnnotations(applicationModel).SingleOrDefault(a => a.Term == termStringValue) as IEdmValueAnnotation; IEdmValue annotationStringValue = expressionEvaluator.Evaluate(annotationString.Value, (IEdmStructuredValue)contextPropertyValue.Value); Assert.AreEqual("98052-0000", ((IEdmStringValue)annotationStringValue).Value, "Term annotation value"); }
public void GetEdmModel_PropertyWithETag_IsConcurrencyToken_HasVocabularyAnnotation() { // Arrange ODataModelBuilder builder = new ODataModelBuilder(); EntityTypeConfiguration <Customer> customer = builder.EntityType <Customer>(); customer.HasKey(c => c.Id); customer.Property(c => c.Id); customer.Property(c => c.Name).IsConcurrencyToken(); builder.EntitySet <Customer>("Customers"); // Act IEdmModel model = builder.GetEdmModel(); // Assert var customers = model.FindDeclaredEntitySet("Customers"); Assert.NotNull(customers); var annotations = model.FindVocabularyAnnotations <IEdmValueAnnotation>(customers, CoreVocabularyModel.ConcurrencyTerm); IEdmValueAnnotation concurrencyAnnotation = Assert.Single(annotations); IEdmCollectionExpression properties = concurrencyAnnotation.Value as IEdmCollectionExpression; Assert.NotNull(properties); Assert.Equal(1, properties.Elements.Count()); var element = properties.Elements.First() as IEdmPathExpression; Assert.NotNull(element); string path = Assert.Single(element.Path); Assert.Equal("Name", path); }
public void ValueTerm_TypeTerm_If_OnEntityContainer() { this.SetupModelsAndValues(); const string applicationCsdl = @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Annotations Target=""foo.fooContainer""> <Annotation Term=""bar.Int32Value""> <If> <Apply Function=""Functions.True"" /> <Int>999</Int> <Int>30</Int> </If> </Annotation> </Annotations> </Schema>"; IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel, this.operationsModel); EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup); IEdmEntityContainer container = this.baseModel.FindEntityContainer("fooContainer"); IEdmValueTerm termInt32Value = this.vocabularyDefinitionModel.FindValueTerm("bar.Int32Value"); IEdmValueAnnotation valueAnnotation = applicationModel.FindVocabularyAnnotations <IEdmValueAnnotation>(container, termInt32Value).SingleOrDefault(); // ?? why do I need a context here? IEdmValue valueOfValueAnnotation = expressionEvaluator.Evaluate(valueAnnotation.Value, this.personValue); Assert.AreEqual(999, ((IEdmIntegerValue)valueOfValueAnnotation).Value, "Value annotation evaluated value."); }
public void ValueTerm_OperationApplication_WithOverloads_OnEntitySet() { this.SetupModelsAndValues(); const string applicationCsdl = @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Annotations Target=""foo.fooContainer/PersonSet""> <Annotation Term=""bar.StringValue""> <If> <Apply Function=""Functions.True"" /> <Apply Function=""Functions.StringConcat""> <String>1</String> <String>2</String> <String>3</String> </Apply> <String>foo</String> </If> </Annotation> </Annotations> </Schema>"; IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel, this.operationsModel); EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup); IEdmEntitySet personSet = this.baseModel.FindEntityContainer("fooContainer").FindEntitySet("PersonSet"); IEdmValueTerm term = this.vocabularyDefinitionModel.FindValueTerm("bar.StringValue"); IEdmValueAnnotation valueAnnotation = applicationModel.FindVocabularyAnnotations <IEdmValueAnnotation>(personSet, term).SingleOrDefault(); IEdmValue valueOfAnnotation = expressionEvaluator.Evaluate(valueAnnotation.Value, this.personValue); Assert.AreEqual("123", ((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."); IEdmValueAnnotation randomTermAnnotation = applicationModel.FindVocabularyAnnotations <IEdmValueAnnotation>(person, "bar.RandomTerm").Single(); random = evaluator.EvaluateToClrValue <string>(randomTermAnnotation.Value, context); Assert.AreEqual("Extra value!", random, "Annotation evaluated value."); }
public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmNavigationSource navigationSource) { Contract.Assert(model != null); Contract.Assert(navigationSource != null); IEnumerable <IEdmStructuralProperty> cachedProperties; if (_concurrencyProperties != null && _concurrencyProperties.TryGetValue(navigationSource, out cachedProperties)) { return(cachedProperties); } IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>(); IEdmEntityType entityType = navigationSource.EntityType(); IEdmVocabularyAnnotatable annotatable = navigationSource as IEdmVocabularyAnnotatable; IEdmContainedEntitySet navigationSourceAsEntitySet = navigationSource as IEdmContainedEntitySet; if (navigationSourceAsEntitySet != null) { annotatable = navigationSourceAsEntitySet.NavigationProperty as EdmNavigationProperty; } if (annotatable != null) { IEdmValueAnnotation annotation = model.FindVocabularyAnnotations <IEdmValueAnnotation>(annotatable, CoreVocabularyModel.ConcurrencyTerm).FirstOrDefault(); if (annotation != null) { IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression; if (properties != null) { foreach (var property in properties.Elements) { IEdmPathExpression pathExpression = property as IEdmPathExpression; if (pathExpression != null) { // So far, we only consider the single path, because only the direct properties from declaring type are used. // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472 string propertyName = pathExpression.Path.Single(); IEdmProperty edmProperty = entityType.FindProperty(propertyName); IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty; if (structuralProperty != null) { results.Add(structuralProperty); } } } } } } if (_concurrencyProperties == null) { _concurrencyProperties = new ConcurrentDictionary <IEdmNavigationSource, IEnumerable <IEdmStructuralProperty> >(); } _concurrencyProperties[navigationSource] = results; return(results); }
internal void WriteValueAnnotationElementHeader(IEdmValueAnnotation annotation, bool isInline) { this.xmlWriter.WriteStartElement(CsdlConstants.Element_Annotation); this.WriteRequiredAttribute(CsdlConstants.Attribute_Term, annotation.Term, this.TermAsXml); this.WriteOptionalAttribute(CsdlConstants.Attribute_Qualifier, annotation.Qualifier, EdmValueWriter.StringAsXml); if (isInline) { this.WriteInlineExpression(annotation.Value); } }
internal void WriteValueAnnotationElementHeader(IEdmValueAnnotation annotation, bool isInline) { this.xmlWriter.WriteStartElement("ValueAnnotation"); this.WriteRequiredAttribute <IEdmTerm>("Term", annotation.Term, new Func <IEdmTerm, string>(this.TermAsXml)); this.WriteOptionalAttribute <string>("Qualifier", annotation.Qualifier, new Func <string, string>(EdmValueWriter.StringAsXml)); if (isInline) { this.WriteInlineExpression(annotation.Value); } }
public void ValueTerm_Constant_OnProperty() { this.SetupModelsAndValues(); const string applicationCsdl = @"<Schema Namespace=""Annotations"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Annotations Target=""foo.Person/CoolnessIndex""> <Annotation Term=""bar.Int32Value"" Qualifier=""HotIndex"" Int=""-1"" /> <Annotation Term=""bar.StringValue"" String=""Goofy"" /> </Annotations> </Schema>"; IEdmModel applicationModel = this.Parse(applicationCsdl, this.baseModel, this.vocabularyDefinitionModel); EdmExpressionEvaluator expressionEvaluator = new EdmExpressionEvaluator(this.operationsLookup); EdmToClrEvaluator clrEvaluator = new EdmToClrEvaluator(this.operationsLookup); IEdmEntityType person = this.baseModel.FindEntityType("foo.Person"); IEdmProperty property = person.FindProperty("CoolnessIndex"); IEdmPropertyValue contextPropertyValue = ((IEdmStructuredValue)this.personValue).FindPropertyValue("CoolnessIndex"); IEdmValueTerm termInt32Value = this.vocabularyDefinitionModel.FindValueTerm("bar.Int32Value"); IEdmValueTerm termStringValue = this.vocabularyDefinitionModel.FindValueTerm("bar.StringValue"); IEdmValueAnnotation annotation = property.VocabularyAnnotations(applicationModel).SingleOrDefault(a => a.Term == termInt32Value) as IEdmValueAnnotation; IEdmExpression expression = annotation.Value; IEdmValue annotationHotIndex = expressionEvaluator.Evaluate(expression); Assert.AreEqual(-1, ((IEdmIntegerValue)annotationHotIndex).Value, "Term annotation value"); annotationHotIndex = applicationModel.GetTermValue(property, termInt32Value, "HotIndex", expressionEvaluator); Assert.AreEqual(-1, ((IEdmIntegerValue)annotationHotIndex).Value, "Term annotation value"); annotationHotIndex = applicationModel.GetTermValue(property, "bar.Int32Value", "HotIndex", expressionEvaluator); Assert.AreEqual(-1, ((IEdmIntegerValue)annotationHotIndex).Value, "Term annotation value"); int hotIndex = applicationModel.GetTermValue <int>(property, termInt32Value, "HotIndex", clrEvaluator); Assert.AreEqual(-1, hotIndex, "Term annotation value"); hotIndex = applicationModel.GetTermValue <int>(property, "bar.Int32Value", "HotIndex", clrEvaluator); Assert.AreEqual(-1, hotIndex, "Term annotation value"); IEdmValue annotationString = applicationModel.GetTermValue(property, termStringValue, expressionEvaluator); Assert.AreEqual("Goofy", ((IEdmStringValue)annotationString).Value, "Term annotation value"); annotationString = applicationModel.GetTermValue(property, "bar.StringValue", expressionEvaluator); Assert.AreEqual("Goofy", ((IEdmStringValue)annotationString).Value, "Term annotation value"); string stringValue = applicationModel.GetTermValue <string>(property, termStringValue, clrEvaluator); Assert.AreEqual("Goofy", stringValue, "Term annotation value"); stringValue = applicationModel.GetTermValue <string>(property, "bar.StringValue", clrEvaluator); Assert.AreEqual("Goofy", stringValue, "Term annotation value"); }
private void ValidateClrObjectConverter <T>(IEdmValueAnnotation valueAnnotation, T expected) { switch (valueAnnotation.Value.ExpressionKind) { case EdmExpressionKind.Record: case EdmExpressionKind.Collection: var actual = this.ConvertToClrObject <T>(valueAnnotation); Assert.IsTrue(CompareObjects(expected, actual), "The actual object content is different from the expected one."); break; } }
protected override void ProcessValueAnnotation(IEdmValueAnnotation annotation) { bool isInline = IsInlineExpression(annotation.Value); this.BeginElement <IEdmValueAnnotation>(annotation, t => this.schemaWriter.WriteValueAnnotationElementHeader(t, isInline), new Action <IEdmValueAnnotation> [0]); if (!isInline) { base.ProcessValueAnnotation(annotation); } this.EndElement(annotation); }
/// <summary> /// Gets vocabulary annotation that binds to a term and a qualifier from the metadata annotation dictionary in current data service context for a specified type. /// </summary> /// <param name="context">The data service context.</param> /// <param name="type">The specified annotated type.</param> /// <param name="term">The term name.</param> /// <param name="qualifier">The qualifier name.</param> /// <returns>The vacabulary annotation that binds to a term and a qualifier for the specified annotated type.</returns> private static IEdmValueAnnotation GetOrInsertCachedMetadataAnnotationForType(DataServiceContext context, Type type, string term, string qualifier) { var serviceModel = context.Format.ServiceModel; if (serviceModel == null) { return(null); } IEdmValueAnnotation edmValueAnnotation = GetCachedMetadataAnnotation(context, type, term, qualifier); if (edmValueAnnotation != null) { return(edmValueAnnotation); } IEdmVocabularyAnnotatable edmVocabularyAnnotatable = null; if (type.IsSubclassOf(typeof(DataServiceContext))) { edmVocabularyAnnotatable = serviceModel.EntityContainer; } else { var serversideName = context.ResolveName == null ? type.FullName : context.ResolveName(type); if (!string.IsNullOrWhiteSpace(serversideName)) { edmVocabularyAnnotatable = serviceModel.FindDeclaredType(serversideName); if (edmVocabularyAnnotatable == null) { return(null); } } } // Gets the annotations which exactly match the qualifier and target. var edmValueAnnotations = serviceModel.FindVocabularyAnnotations <IEdmValueAnnotation>(edmVocabularyAnnotatable, term, qualifier) .Where(a => a.Qualifier == qualifier && a.Target == edmVocabularyAnnotatable); if (edmValueAnnotations.Count() == 0) { edmValueAnnotation = GetOrInsertCachedMetadataAnnotationForType(context, type.GetBaseType(), term, qualifier); } else if (edmValueAnnotations.Count() == 1) { edmValueAnnotation = edmValueAnnotations.Single(); } InsertMetadataAnnotation(context, type, edmValueAnnotation); return(edmValueAnnotation); }
/// <summary> /// Gets vocabulary annotation that binds to a term and a qualifier from the metadata annotation dictionary in current data service context for a specified methodInfo. /// </summary> /// <param name="context">The data service context.</param> /// <param name="methodInfo">The specified annotated methodInfo.</param> /// <param name="term">The term name.</param> /// <param name="qualifier">The qualifier name.</param> /// <returns>The vacabulary annotation that binds to a term and a qualifier for the specified annotated methodInfo.</returns> private static IEdmValueAnnotation GetOrInsertCachedMetadataAnnotationForMethodInfo(DataServiceContext context, MethodInfo methodInfo, string term, string qualifier) { IEdmModel serviceModel = context.Format.ServiceModel; if (serviceModel == null) { return(null); } IEdmValueAnnotation edmValueAnnotation = GetCachedMetadataAnnotation(context, methodInfo, term, qualifier); if (edmValueAnnotation != null) { return(edmValueAnnotation); } IEdmVocabularyAnnotatable edmVocabularyAnnotatable = context.GetEdmOperationOrOperationImport(methodInfo); if (edmVocabularyAnnotatable == null) { return(null); } var edmOperationImport = edmVocabularyAnnotatable as IEdmOperationImport; IEnumerable <IEdmValueAnnotation> edmValueAnnotations = null; if (edmOperationImport != null) { edmValueAnnotations = serviceModel.FindVocabularyAnnotations <IEdmValueAnnotation>(edmOperationImport, term, qualifier) .Where(a => a.Qualifier == qualifier); if (!edmValueAnnotations.Any()) { edmVocabularyAnnotatable = edmOperationImport.Operation; } } if (edmValueAnnotations == null || !edmValueAnnotations.Any()) { edmValueAnnotations = serviceModel.FindVocabularyAnnotations <IEdmValueAnnotation>(edmVocabularyAnnotatable, term, qualifier) .Where(a => a.Qualifier == qualifier); } if (edmValueAnnotations != null && edmValueAnnotations.Count() == 1) { edmValueAnnotation = edmValueAnnotations.Single(); InsertMetadataAnnotation(context, methodInfo, edmValueAnnotation); return(edmValueAnnotation); } return(null); }
private string GetStringAnnotationValue(IEdmVocabularyAnnotatable annotatable, string annotationNamespace, string annotationName) { // Find only direct annotation which have a string constant value IEdmValueAnnotation annotation = annotatable.VocabularyAnnotations(Model). OfType <IEdmValueAnnotation>(). FirstOrDefault( a => a.Term.Namespace.Equals(annotationNamespace) && a.Term.Name.Equals(annotationName) && a.Value.ExpressionKind == EdmExpressionKind.StringConstant && a.Target.Equals(annotatable)); return(annotation != null ? (annotation.Value as IEdmStringConstantExpression).Value : null); }
public void ModelBuilderTest() { const string expectMetadata = " <EntitySet Name=\"ETagUntypedCustomers\" EntityType=\"NS.Customer\">\r\n" + " <Annotation Term=\"Org.OData.Core.V1.OptimisticConcurrency\">\r\n" + " <Collection>\r\n" + " <PropertyPath>Name</PropertyPath>\r\n" + " </Collection>\r\n" + " </Annotation>\r\n" + " </EntitySet>"; string requestUri = string.Format("{0}/odata/$metadata", this.BaseAddress); HttpResponseMessage response = this.Client.GetAsync(requestUri).Result; var content = response.Content.ReadAsStringAsync().Result; Assert.Contains(expectMetadata, content); var stream = response.Content.ReadAsStreamAsync().Result; IODataResponseMessage message = new ODataMessageWrapper(stream, response.Content.Headers); var reader = new ODataMessageReader(message); var edmModel = reader.ReadMetadataDocument(); Assert.NotNull(edmModel); var etagCustomers = edmModel.FindDeclaredEntitySet("ETagUntypedCustomers"); Assert.NotNull(etagCustomers); var annotations = edmModel.FindDeclaredVocabularyAnnotations(etagCustomers); IEdmVocabularyAnnotation annotation = Assert.Single(annotations); Assert.NotNull(annotation); Assert.Same(CoreVocabularyModel.ConcurrencyTerm, annotation.Term); Assert.Same(etagCustomers, annotation.Target); IEdmValueAnnotation valueAnnotation = annotation as IEdmValueAnnotation; Assert.NotNull(valueAnnotation); Assert.NotNull(valueAnnotation.Value); IEdmCollectionExpression collection = valueAnnotation.Value as IEdmCollectionExpression; Assert.NotNull(collection); Assert.Equal(new[] { "Name" }, collection.Elements.Select(e => ((IEdmPathExpression)e).Path.Single())); }
private T ConvertToClrObject <T>(IEdmValueAnnotation valueAnnotation) { var edmClrEvaluator = new EdmToClrEvaluator(this.operationDefinitions); var edmClrConverter = new EdmToClrConverter(); var edmValue = edmClrEvaluator.Evaluate(valueAnnotation.Value); var object1 = edmClrEvaluator.EvaluateToClrValue <T>(valueAnnotation.Value); var object2 = (T)edmClrConverter.AsClrValue(edmValue, typeof(T)); var object3 = edmClrEvaluator.EdmToClrConverter.AsClrValue <T>(edmValue); Assert.IsTrue(CompareObjects(object1, object2), "The results of EvaluateToClrValue and AsClrValue do not match."); Assert.IsTrue(CompareObjects(object2, object3), "The result of the generic version of AsClrValue does not match that of the non-generic version."); return(object1); }
void GetAnnotation() { Uri metadataUri = context.GetMetadataUri(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(metadataUri); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream stream = response.GetResponseStream(); StreamReader sr = new StreamReader(stream); stream.Flush(); string metadata = sr.ReadToEnd(); IEdmModel annotatedModel; IEnumerable <EdmError> errors; XmlReader xmlReader = XmlReader.Create(new StringReader(metadata)); bool parsed = EdmxReader.TryParse(xmlReader, out annotatedModel, out errors); foreach (IEdmVocabularyAnnotation annotation in annotatedModel.VocabularyAnnotations) { if (annotation.Term.TermKind != EdmTermKind.Value) { continue; } IEdmValueAnnotation valueAnnotation = (IEdmValueAnnotation)annotation; IEdmProperty property = (IEdmProperty)valueAnnotation.Target; IEdmTerm term = valueAnnotation.Term; string entityTypeName = ((IEdmSchemaType)property.DeclaringType).Name; if (!annotations.ContainsKey(entityTypeName)) { annotations.Add(entityTypeName, new Dictionary <string, XpoAnnotation>()); } if (!annotations[entityTypeName].ContainsKey(property.Name)) { annotations[entityTypeName][property.Name] = new XpoAnnotation(); } switch (term.Name) { case "Size": annotations[entityTypeName][property.Name].Size = (int)((IEdmIntegerValue)valueAnnotation.Value).Value; break; case "ReadOnly": annotations[entityTypeName][property.Name].ReadOnly = ((IEdmBooleanValue)valueAnnotation.Value).Value; break; } } }
private void CompareTermAnnotationContent(IEdmVocabularyAnnotation expectedTermAnnotation, IEdmVocabularyAnnotation actualTermAnnotation) { this.SatisfiesEquals(expectedTermAnnotation.Term.TermKind, actualTermAnnotation.Term.TermKind, "Term Kind mismatch at {0}.", this.scopeContext); if (expectedTermAnnotation.Term.TermKind == EdmTermKind.Value) { IEdmValueAnnotation expectedValueAnnotation = (IEdmValueAnnotation)expectedTermAnnotation; IEdmValueAnnotation actualValueAnnotation = (IEdmValueAnnotation)actualTermAnnotation; // TODO: push Expression Equals() and ToString() to product? this.SatisfiesCondition(this.CompareIEdmExpression(expectedValueAnnotation.Value, actualValueAnnotation.Value), "Value expression mismatch at {0}.", this.scopeContext); } else { this.WriteErrorMessage("Unexpected TermKind {0} at {1}.", expectedTermAnnotation.Term.TermKind, this.scopeContext); } }
public static bool IsConcurrencyCheckEnabled(this IEdmModel model, IEdmEntitySet entitySet) { bool needCurrencyCheck; if (concurrencyCheckFlags.TryGetValue(entitySet, out needCurrencyCheck)) { return(needCurrencyCheck); } needCurrencyCheck = false; var annotations = model.FindVocabularyAnnotations <IEdmValueAnnotation>( entitySet, CoreVocabularyModel.ConcurrencyTerm); IEdmValueAnnotation annotation = annotations.FirstOrDefault(); if (annotation != null) { needCurrencyCheck = true; } concurrencyCheckFlags[entitySet] = needCurrencyCheck; return(needCurrencyCheck); }
public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmEntitySet entitySet) { Contract.Assert(model != null); Contract.Assert(entitySet != null); IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>(); IEdmEntityType entityType = entitySet.EntityType(); var annotations = model.FindVocabularyAnnotations <IEdmValueAnnotation>(entitySet, CoreVocabularyModel.ConcurrencyTerm); IEdmValueAnnotation annotation = annotations.FirstOrDefault(); if (annotation != null) { IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression; if (properties != null) { foreach (var property in properties.Elements) { IEdmPathExpression pathExpression = property as IEdmPathExpression; if (pathExpression != null) { // So far, we only consider the single path, because only the direct properties from declaring type are used. // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472 string propertyName = pathExpression.Path.Single(); IEdmProperty edmProperty = entityType.FindProperty(propertyName); IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty; if (structuralProperty != null) { results.Add(structuralProperty); } } } } } return(results); }
/// <summary> /// Determines whether or not the annotation indicates the 'KeyAsSegment' url-convention. /// </summary> /// <param name="annotation">The annotation to check.</param> /// <returns>True if the annotation indicates the 'KeyAsSegment' url convention; false otherwise.</returns> private static bool IsKeyAsSegmentUrlConventionAnnotation(IEdmValueAnnotation annotation) { return(annotation != null && IsUrlConventionTerm(annotation.Term) && IsKeyAsSegment(annotation.Value)); }
/// <summary> /// Determines whether or not the annotation indicates the 'KeyAsSegment' url-convention. /// </summary> /// <param name="annotation">The annotation to check.</param> /// <returns>True if the annotation indicates the 'KeyAsSegment' url convention; false otherwise.</returns> private static bool IsKeyAsSegmentUrlConventionAnnotation(IEdmValueAnnotation annotation) { return annotation != null && IsUrlConventionTerm(annotation.Term) && IsKeyAsSegment(annotation.Value); }
/// <summary> /// Gets vocabulary annotation that binds to a term and a qualifier from the metadata annotation dictionary in current data service context for a specified propertyInfo. /// </summary> /// <param name="context">The data service context.</param> /// <param name="propertyInfo">The specified annotated propertyInfo.</param> /// <param name="term">The term name.</param> /// <param name="qualifier">The qualifier name.</param> /// <returns>The vacabulary annotation that binds to a term and a qualifier for the specified annotated propertyInfo.</returns> private static IEdmValueAnnotation GetOrInsertCachedMetadataAnnotationForPropertyInfo(DataServiceContext context, PropertyInfo propertyInfo, string term, string qualifier) { var serviceModel = context.Format.ServiceModel; if (serviceModel == null) { return(null); } IEdmValueAnnotation edmValueAnnotation = GetCachedMetadataAnnotation(context, propertyInfo, term, qualifier); if (edmValueAnnotation != null) { return(edmValueAnnotation); } var severSidePropertyName = ClientTypeUtil.GetServerDefinedName(propertyInfo); if (string.IsNullOrEmpty(severSidePropertyName)) { return(null); } var declaringType = propertyInfo.DeclaringType; IEnumerable <IEdmValueAnnotation> edmValueAnnotations = null; if (declaringType.IsSubclassOf(typeof(DataServiceContext))) { var entityContainer = serviceModel.EntityContainer; var edmEntityContainerElements = entityContainer.Elements.Where(e => e.Name == severSidePropertyName); if (edmEntityContainerElements != null && edmEntityContainerElements.Count() == 1) { edmValueAnnotations = serviceModel.FindVocabularyAnnotations <IEdmValueAnnotation>( edmEntityContainerElements.Single(), term, qualifier).Where(a => a.Qualifier == qualifier); } } else { var serversideTypeName = context.ResolveName == null ? declaringType.FullName : context.ResolveName(declaringType); var edmType = serviceModel.FindDeclaredType(serversideTypeName); if (edmType != null) { var edmStructuredType = edmType as IEdmStructuredType; if (edmStructuredType != null) { var edmProperty = edmStructuredType.FindProperty(severSidePropertyName); if (edmProperty != null) { edmValueAnnotations = serviceModel.FindVocabularyAnnotations <IEdmValueAnnotation>( edmProperty, term, qualifier).Where(a => a.Qualifier == qualifier); } } } } if (edmValueAnnotations != null && edmValueAnnotations.Count() == 1) { edmValueAnnotation = edmValueAnnotations.Single(); InsertMetadataAnnotation(context, propertyInfo, edmValueAnnotation); return(edmValueAnnotation); } return(null); }
/// <summary> /// Gets the CLR value of a term that has been applied to the specified object /// </summary> /// <typeparam name="TResult">The CLR type of the annotation to be returned.</typeparam> /// <param name="context">The data service context.</param> /// <param name="source">The specified annotated object instance.</param> /// <param name="term">The term name.</param> /// <param name="qualifier">The qualifier name.</param> /// <param name="annotationValue">Value of the term evaluated.</param> /// <returns>True if the annotation value can be evaluated, else false.</returns> internal static bool TryGetMetadataAnnotation <TResult>(DataServiceContext context, object source, string term, string qualifier, out TResult annotationValue) { IEdmValueAnnotation edmValueAnnotation = null; ClientEdmStructuredValue clientEdmValue = null; PropertyInfo propertyInfo = null; MethodInfo methodInfo = null; var keyValue = source as Tuple <object, MemberInfo>; if (keyValue != null) { // Get metadata annotation defined on property or Navigation property or Operation or OperationImport var instance = keyValue.Item1; var memberInfo = keyValue.Item2; propertyInfo = memberInfo as PropertyInfo; methodInfo = memberInfo as MethodInfo; if (instance != null) { IEdmType edmType = context.Model.GetOrCreateEdmType(instance.GetType()); if (edmType is IEdmStructuredType) { ClientTypeAnnotation clientTypeAnnotation = context.Model.GetClientTypeAnnotation(edmType); clientEdmValue = new ClientEdmStructuredValue(instance, context.Model, clientTypeAnnotation); } } } else { if (propertyInfo == null) { propertyInfo = source as PropertyInfo; } if (methodInfo == null) { methodInfo = source as MethodInfo; } } if (propertyInfo != null) { edmValueAnnotation = GetOrInsertCachedMetadataAnnotationForPropertyInfo(context, propertyInfo, term, qualifier); return(TryEvaluateMetadataAnnotation(context, edmValueAnnotation, clientEdmValue, out annotationValue)); } if (methodInfo != null) { edmValueAnnotation = GetOrInsertCachedMetadataAnnotationForMethodInfo(context, methodInfo, term, qualifier); return(TryEvaluateMetadataAnnotation(context, edmValueAnnotation, clientEdmValue, out annotationValue)); } var type = source as Type; Type underlyingType = type; if (type == null) { type = source.GetType(); underlyingType = Nullable.GetUnderlyingType(type) ?? type; // For complex type or entity type instance, try to convert the instance to ClientEdmStructuredValue for further evaluation. IEdmType edmType = context.Model.GetOrCreateEdmType(underlyingType); if (edmType is IEdmStructuredType) { ClientTypeAnnotation clientTypeAnnotation = context.Model.GetClientTypeAnnotation(edmType); clientEdmValue = new ClientEdmStructuredValue(source, context.Model, clientTypeAnnotation); } } edmValueAnnotation = GetOrInsertCachedMetadataAnnotationForType(context, underlyingType, term, qualifier); return(TryEvaluateMetadataAnnotation(context, edmValueAnnotation, clientEdmValue, out annotationValue)); }
public void ParseCapabilityAnnotation(OdcmObject odcmObject, IEdmValueAnnotation annotation) { TryParseCapability(odcmObject, annotation.Value, annotation.Term.FullName()); }
/// <summary> /// Insert an metadata annotation with the provided key to the metadata annotation dictionary. /// </summary> /// <param name="context">The data service context</param> /// <param name="key">The specified key</param> /// <param name="edmValueAnnotation">The metadata annotation to be inserted.</param> private static void InsertMetadataAnnotation(DataServiceContext context, object key, IEdmValueAnnotation edmValueAnnotation) { if (edmValueAnnotation != null) { IList <IEdmValueAnnotation> edmValueAnnotations; if (!context.MetadataAnnotationsDictionary.TryGetValue(key, out edmValueAnnotations)) { edmValueAnnotations = new List <IEdmValueAnnotation>(); context.MetadataAnnotationsDictionary.Add(key, edmValueAnnotations); } edmValueAnnotations.Add(edmValueAnnotation); } }
/// <summary> /// Evaluate IEdmValueAnnotation to an CLR object /// </summary> /// <typeparam name="TResult">The CLR type of the annotation to be returned.</typeparam> /// <param name="context">The data service context.</param> /// <param name="edmValueAnnotation">IEdmValueAnnotation to be evaluated.</param> /// <param name="clientEdmValue">Value to use as context in evaluating the expression.</param> /// <param name="annotationValue">Value of the term evaluated.</param> /// <returns>True if the annotation value can be evaluated, else false.</returns> private static bool TryEvaluateMetadataAnnotation <TResult>(DataServiceContext context, IEdmValueAnnotation edmValueAnnotation, ClientEdmStructuredValue clientEdmValue, out TResult annotationValue) { if (edmValueAnnotation == null) { annotationValue = default(TResult); return(false); } EdmToClrEvaluator evaluator = CreateEdmToClrEvaluator(context); try { annotationValue = evaluator.EvaluateToClrValue <TResult>(edmValueAnnotation.Value, clientEdmValue); } catch (InvalidOperationException) { // When expression contains Path. if the clientEdmValue is null, or the related property is not valid property of the clientEdmValue. // TheEvaluateToClrValue might throw InvalidOperationException; annotationValue = default(TResult); return(false); } return(true); }
private List<PropertyValue> GetAnnotationValueList(EdmExpressionKind expressionKind, IEdmValueAnnotation valueAnnotation) { return this.GetAnnotationValueList(expressionKind, valueAnnotation.Value); }
protected virtual void ProcessValueAnnotation(IEdmValueAnnotation annotation) { this.ProcessVocabularyAnnotation(annotation); this.VisitExpression(annotation.Value); }
public void ModelBuilderTest() { const string expectMetadata = " <EntitySet Name=\"ETagsCustomers\" EntityType=\"WebStack.QA.Test.OData.ETags.ETagsCustomer\">\r\n" + " <Annotation Term=\"Org.OData.Core.V1.OptimisticConcurrency\">\r\n" + " <Collection>\r\n" + " <PropertyPath>Id</PropertyPath>\r\n" + " <PropertyPath>Name</PropertyPath>\r\n" + " <PropertyPath>BoolProperty</PropertyPath>\r\n" + " <PropertyPath>ByteProperty</PropertyPath>\r\n" + " <PropertyPath>CharProperty</PropertyPath>\r\n" + " <PropertyPath>DecimalProperty</PropertyPath>\r\n" + " <PropertyPath>DoubleProperty</PropertyPath>\r\n" + " <PropertyPath>ShortProperty</PropertyPath>\r\n" + " <PropertyPath>LongProperty</PropertyPath>\r\n" + " <PropertyPath>SbyteProperty</PropertyPath>\r\n" + " <PropertyPath>FloatProperty</PropertyPath>\r\n" + " <PropertyPath>UshortProperty</PropertyPath>\r\n" + " <PropertyPath>UintProperty</PropertyPath>\r\n" + " <PropertyPath>UlongProperty</PropertyPath>\r\n" + " <PropertyPath>GuidProperty</PropertyPath>\r\n" + " <PropertyPath>DateTimeOffsetProperty</PropertyPath>\r\n" + " <PropertyPath>StringWithConcurrencyCheckAttributeProperty</PropertyPath>\r\n" + " </Collection>\r\n" + " </Annotation>\r\n" + " </EntitySet>"; string requestUri = string.Format("{0}/odata/$metadata", this.BaseAddress); HttpResponseMessage response = this.Client.GetAsync(requestUri).Result; var content = response.Content.ReadAsStringAsync().Result; Assert.Contains(expectMetadata, content); var stream = response.Content.ReadAsStreamAsync().Result; IODataResponseMessage message = new ODataMessageWrapper(stream, response.Content.Headers); var reader = new ODataMessageReader(message); var edmModel = reader.ReadMetadataDocument(); Assert.NotNull(edmModel); var etagCustomers = edmModel.FindDeclaredEntitySet("ETagsCustomers"); Assert.NotNull(etagCustomers); var annotations = edmModel.FindDeclaredVocabularyAnnotations(etagCustomers); IEdmVocabularyAnnotation annotation = Assert.Single(annotations); Assert.NotNull(annotation); Assert.Same(CoreVocabularyModel.ConcurrencyTerm, annotation.Term); Assert.Same(etagCustomers, annotation.Target); IEdmValueAnnotation valueAnnotation = annotation as IEdmValueAnnotation; Assert.NotNull(valueAnnotation); Assert.NotNull(valueAnnotation.Value); IEdmCollectionExpression collection = valueAnnotation.Value as IEdmCollectionExpression; Assert.NotNull(collection); Assert.Equal(new[] { "Id", "Name", "BoolProperty", "ByteProperty", "CharProperty", "DecimalProperty", "DoubleProperty", "ShortProperty", "LongProperty", "SbyteProperty", "FloatProperty", "UshortProperty", "UintProperty", "UlongProperty", "GuidProperty", "DateTimeOffsetProperty", "StringWithConcurrencyCheckAttributeProperty" }, collection.Elements.Select(e => ((IEdmPathExpression)e).Path.Single())); }