/// <summary> /// Converts a LinqNewExpression to a Complex Instance /// </summary> /// <param name="expression">Expression to convert to a ComplexInstance</param> /// <returns>Complex Instance</returns> internal static ComplexInstance ConvertToComplexInstance(this QueryExpression expression) { var nullConstantExpression = expression as QueryNullExpression; var queryComplexType = (QueryComplexType)expression.ExpressionType; if (nullConstantExpression != null) { return(new ComplexInstance(queryComplexType.ComplexType.FullName, true)); } var structuralExpression = expression as LinqNewInstanceExpression; var newComplexInstance = new ComplexInstance(queryComplexType.ComplexType.FullName, false); ExceptionUtilities.Assert(structuralExpression.MemberNames.Count == structuralExpression.Members.Count, "MemberNames and Members count are not equal"); for (int i = 0; i < structuralExpression.MemberNames.Count; i++) { string memberName = structuralExpression.MemberNames[i]; var memberExpression = structuralExpression.Members[i]; var memberProperty = queryComplexType.ComplexType.Properties.Single(p => p.Name == memberName); var complexDataType = memberProperty.PropertyType as ComplexDataType; var collectionDataType = memberProperty.PropertyType as CollectionDataType; if (complexDataType != null) { var childComplexInstance = memberExpression.ConvertToComplexInstance(); var complexProperty = new ComplexProperty() { Name = memberName, Value = childComplexInstance }; newComplexInstance.Add(complexProperty); } else if (collectionDataType != null) { var collectionPropertyType = memberProperty.PropertyType as CollectionDataType; var convertedValue = memberExpression.ConvertToMultiValue(collectionPropertyType.ElementDataType); if (collectionPropertyType.ElementDataType is ComplexDataType) { newComplexInstance.Add(new ComplexMultiValueProperty(memberName, convertedValue as ComplexMultiValue)); } else { var primitiveDataType = collectionPropertyType.ElementDataType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Not a primitiveDataType '{0}'", collectionPropertyType.ElementDataType); newComplexInstance.Add(new PrimitiveMultiValueProperty(memberName, convertedValue as PrimitiveMultiValue)); } } else { var primitiveDataType = memberProperty.PropertyType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Expected a PrimitiveDataType"); var primitiveValue = memberExpression.ConvertToPrimitiveValue(primitiveDataType); newComplexInstance.Add(new PrimitiveProperty(memberName, primitiveDataType.GetEdmTypeName(), primitiveValue.ClrValue)); } } return(newComplexInstance); }
private void PopulatePropertiesFromPaths(ComplexInstance instance, IEnumerable <MemberProperty> properties, string propertyPath, IEnumerable <NamedValue> namedValues) { ExceptionUtilities.CheckArgumentNotNull(instance, "instance"); ExceptionUtilities.CheckArgumentNotNull(properties, "properties"); ExceptionUtilities.CheckArgumentNotNull(namedValues, "namedValues"); foreach (MemberProperty property in properties) { string childPropertyPath = property.Name; if (propertyPath != null) { childPropertyPath = propertyPath + "." + property.Name; } CollectionDataType collectionDataType = property.PropertyType as CollectionDataType; PrimitiveDataType primitiveDataType = property.PropertyType as PrimitiveDataType; if (primitiveDataType != null) { NamedValue memberPropertyNamedValue = namedValues.SingleOrDefault(nv => nv.Name == childPropertyPath); if (memberPropertyNamedValue != null) { instance.Add(this.PrimitiveProperty(property, memberPropertyNamedValue.Value)); } } else if (collectionDataType != null) { IEnumerable <NamedValue> bagNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (bagNamedValues.Count() > 0) { this.PopulateMultiValuePropertyFromPaths(instance, property, collectionDataType.ElementDataType, childPropertyPath, bagNamedValues); } else { this.PopulateCollectionPropertyWithNullOrEmpty(instance, property, childPropertyPath, namedValues); } } else { var complexDataType = property.PropertyType as ComplexDataType; ExceptionUtilities.CheckObjectNotNull(complexDataType, "Property '{0}' was not primitive, a collection, or complex", property.Name); IEnumerable <NamedValue> complexInstanceNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() > 0) { PropertyInstance memberPropertyInstance = this.ComplexProperty(property, childPropertyPath, complexInstanceNamedValues); instance.Add(memberPropertyInstance); } else { // Check for null case IEnumerable <NamedValue> exactMatches = namedValues.Where(nv => nv.Name == childPropertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", childPropertyPath); if (exactMatches.Count() == 1) { instance.Add(new ComplexProperty(property.Name, new ComplexInstance(complexDataType.Definition.FullName, true))); } } } } }
private void PopulatePropertiesFromObject(ComplexInstance instance, IEnumerable <MemberProperty> properties, object anonymous) { ExceptionUtilities.CheckArgumentNotNull(instance, "instance"); ExceptionUtilities.CheckArgumentNotNull(properties, "properties"); ExceptionUtilities.CheckArgumentNotNull(anonymous, "anonymous"); Type anonymousType = anonymous.GetType(); foreach (PropertyInfo info in anonymousType.GetProperties()) { object value = info.GetValue(anonymous, null); MemberProperty property = properties.SingleOrDefault(p => p.Name == info.Name); if (property == null) { instance.Add(this.DynamicProperty(info.Name, info.PropertyType, value)); } else if (property.PropertyType is ComplexDataType) { instance.Add(this.ComplexProperty(property, value)); } else if (property.PropertyType is CollectionDataType) { instance.Add(this.MultiValueProperty(property, value)); } else { instance.Add(this.PrimitiveProperty(property, value)); } } }
/// <summary> /// Converts a queryExpression to a payload where applicable, returns null if not required /// </summary> /// <param name="expression">Expression to convert</param> /// <returns>OData Payload</returns> public ODataPayloadElement ComputePayload(QueryExpression expression) { LinqToAstoriaProcedureExpressionLocatorVisitor visitor = new LinqToAstoriaProcedureExpressionLocatorVisitor(); var procedureExpression = visitor.FindProcedure(expression); if (procedureExpression == null) { return(null); } var actionAnnotation = procedureExpression.Function.Annotations.OfType <ServiceOperationAnnotation>().SingleOrDefault(); ExceptionUtilities.CheckObjectNotNull(actionAnnotation, "Should have an action annotation"); ExceptionUtilities.Assert(procedureExpression.Function.IsAction(), "Visitor did not find a procedure"); var nonboundArguments = procedureExpression.GetNonBoundFunctionArgments(); var parameterKeyValues = procedureExpression.Function.ConvertActionArgumentsToTypedValues(actionAnnotation, nonboundArguments); var complexInstance = new ComplexInstance(null, false); foreach (var parameterKeyValuePair in parameterKeyValues) { var parameterPrimitiveValue = parameterKeyValuePair.Value as PrimitiveValue; var primitiveMultiValue = parameterKeyValuePair.Value as PrimitiveMultiValue; var complexMultiValue = parameterKeyValuePair.Value as ComplexMultiValue; if (parameterPrimitiveValue != null) { complexInstance.Add(new PrimitiveProperty(parameterKeyValuePair.Key, parameterPrimitiveValue.FullTypeName, parameterPrimitiveValue.ClrValue)); } else if (primitiveMultiValue != null) { complexInstance.Add(new PrimitiveMultiValueProperty(parameterKeyValuePair.Key, primitiveMultiValue)); } else if (complexMultiValue != null) { complexInstance.Add(new ComplexMultiValueProperty(parameterKeyValuePair.Key, complexMultiValue)); } else { var parameterComplexInstance = parameterKeyValuePair.Value as ComplexInstance; ExceptionUtilities.CheckObjectNotNull(parameterComplexInstance, "Unsupported type"); complexInstance.Add(new ComplexProperty(parameterKeyValuePair.Key, parameterComplexInstance)); } } return(complexInstance); }
private void PopulateComplexMultiValuePropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable <NamedValue> namedValues, ComplexDataType complexTypeElementDataType) { int i = 0; bool completed = false; var complexCollection = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(complexTypeElementDataType.BuildMultiValueTypeName(), false)); while (!completed) { IEnumerable <NamedValue> complexInstanceNamedValues = namedValues.Where(pp => pp.Name.StartsWith(propertyPath + "." + i + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() == 0) { completed = true; } else { ComplexInstance complexInstance = this.ComplexInstance(complexTypeElementDataType.Definition, propertyPath + "." + i, complexInstanceNamedValues); complexCollection.Value.Add(complexInstance); } i++; } if (i > 1) { instance.Add(complexCollection); } }
private void PopulatePrimitiveBagPropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable <NamedValue> namedValues, PrimitiveDataType primitiveElementDataType) { int i = 0; bool completed = false; var primitiveCollection = new PrimitiveMultiValue(primitiveElementDataType.BuildMultiValueTypeName(), false); while (!completed) { IEnumerable <NamedValue> primitiveItemNamedValues = namedValues.Where(pp => pp.Name == propertyPath + "." + i).ToList(); if (primitiveItemNamedValues.Count() == 0) { completed = true; } else { ExceptionUtilities.Assert(primitiveItemNamedValues.Count() < 2, "Should not get more than one value for a primitive Bag item for path '{0}'", propertyPath + "." + i); var value = primitiveItemNamedValues.Single(); // Do something with the value primitiveCollection.Add(PrimitiveValue(primitiveElementDataType, value.Value)); } i++; } if (i > 1) { instance.Add(new PrimitiveMultiValueProperty(memberProperty.Name, primitiveCollection)); } }
/// <summary> /// Deserialize the element as a complex instance /// </summary> /// <param name="element">The xml representing a complex instance</param> /// <returns>The deserialized complex instance</returns> private ComplexInstance DeserializeComplexInstance(XElement element) { ComplexInstance instance = new ComplexInstance(); // get the type XAttribute type = element.Attribute(MetadataType); if (type != null) { instance.FullTypeName = type.Value; } // check for the null attribute XAttribute isNull = element.Attribute(MetadataNull); if (isNull != null) { instance.IsNull = bool.Parse(isNull.Value); } else if (element.HasElements) { instance.IsNull = false; } // get the properties foreach (XElement subElement in element.Elements()) { instance.Add(this.DeserializeProperty(subElement)); } return(instance); }
/// <summary> /// Because the test deserializer used to parse the actual payload will not have metadata, we fix it up here. /// Note: this should probably move to happen just before comparison, rather than when generating expectations. /// </summary> /// <param name="payloadElement">The payload element</param> private void SortAndNormalizeProperties(ComplexInstance payloadElement) { var sortedProperties = payloadElement.Properties.OrderBy(p => p.Name).ToList(); foreach (var p in sortedProperties) { var property = p; payloadElement.Remove(property); // If we have a primitive property with null value, we write a type name for the null value // in V1 and V2. If not type name is available or we are in V3, we don't do that and thus expect a null property instance. var primitiveProperty = property as PrimitiveProperty; if (primitiveProperty != null && primitiveProperty.Value.IsNull && (this.dsv >= DataServiceProtocolVersion.V4 || string.IsNullOrEmpty(primitiveProperty.Value.FullTypeName))) { property = new NullPropertyInstance(property.Name, null).WithAnnotations(property.Annotations); } var complexProperty = property as ComplexProperty; if (complexProperty != null && complexProperty.Value.IsNull) { property = new NullPropertyInstance(property.Name, complexProperty.Value.FullTypeName).WithAnnotations(property.Annotations); } var complexCollectionProperty = property as ComplexMultiValueProperty; if (complexCollectionProperty != null && complexCollectionProperty.Value.Count == 0 && complexCollectionProperty.Value.FullTypeName == null) { property = new PrimitiveProperty(complexCollectionProperty.Name, complexCollectionProperty.Value.FullTypeName, string.Empty); } payloadElement.Add(property); } }
private PropertyInstance BuildProperty(IEdmProperty property) { if (property.Type.IsCollection()) { var type = (IEdmCollectionType)property.Type.Definition; if (type.ElementType.IsComplex()) { var complex = new ComplexInstance(property.Type.FullName(), false).WithTypeAnnotation(type.ElementType.Definition); foreach (var prop in ((IEdmComplexType)type.ElementType.Definition).StructuralProperties()) { complex.Add(this.BuildProperty(prop)); } return(new ComplexMultiValueProperty(property.Name, new ComplexMultiValue(property.Type.FullName(), false, complex)).WithTypeAnnotation(type)); } return(new PrimitiveMultiValueProperty(property.Name, new PrimitiveMultiValue(property.Type.FullName(), false, this.GetValue((IEdmPrimitiveTypeReference)type.ElementType))).WithTypeAnnotation(property.Type)); } if (property.IsComplex()) { var complex = new ComplexInstance(property.Type.FullName(), false); foreach (var prop in ((IEdmComplexType)property.Type.Definition).StructuralProperties()) { complex.Add(this.BuildProperty(prop)); } return(new ComplexProperty(property.Name, complex).WithTypeAnnotation(property.Type)); } return(new PrimitiveProperty((property.Name), this.GetValue((IEdmPrimitiveTypeReference)property.Type)).WithTypeAnnotation(property.Type)); }
/// <summary> /// Converts a queryExpression to a payload where applicable, returns null if not required /// </summary> /// <param name="expression">Expression to convert</param> /// <returns>OData Payload</returns> public ODataPayloadElement ComputePayload(QueryExpression expression) { LinqToAstoriaProcedureExpressionLocatorVisitor visitor = new LinqToAstoriaProcedureExpressionLocatorVisitor(); var procedureExpression = visitor.FindProcedure(expression); if (procedureExpression == null) { return null; } var actionAnnotation = procedureExpression.Function.Annotations.OfType<ServiceOperationAnnotation>().SingleOrDefault(); ExceptionUtilities.CheckObjectNotNull(actionAnnotation, "Should have an action annotation"); ExceptionUtilities.Assert(procedureExpression.Function.IsAction(), "Visitor did not find a procedure"); var nonboundArguments = procedureExpression.GetNonBoundFunctionArgments(); var parameterKeyValues = procedureExpression.Function.ConvertActionArgumentsToTypedValues(actionAnnotation, nonboundArguments); var complexInstance = new ComplexInstance(null, false); foreach (var parameterKeyValuePair in parameterKeyValues) { var parameterPrimitiveValue = parameterKeyValuePair.Value as PrimitiveValue; var primitiveMultiValue = parameterKeyValuePair.Value as PrimitiveMultiValue; var complexMultiValue = parameterKeyValuePair.Value as ComplexMultiValue; if (parameterPrimitiveValue != null) { complexInstance.Add(new PrimitiveProperty(parameterKeyValuePair.Key, parameterPrimitiveValue.FullTypeName, parameterPrimitiveValue.ClrValue)); } else if (primitiveMultiValue != null) { complexInstance.Add(new PrimitiveMultiValueProperty(parameterKeyValuePair.Key, primitiveMultiValue)); } else if (complexMultiValue != null) { complexInstance.Add(new ComplexMultiValueProperty(parameterKeyValuePair.Key, complexMultiValue)); } else { var parameterComplexInstance = parameterKeyValuePair.Value as ComplexInstance; ExceptionUtilities.CheckObjectNotNull(parameterComplexInstance, "Unsupported type"); complexInstance.Add(new ComplexProperty(parameterKeyValuePair.Key, parameterComplexInstance)); } } return complexInstance; }
private void PopulateCollectionPropertyWithNullOrEmpty(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable <NamedValue> namedValues) { IEnumerable <NamedValue> exactMatches = namedValues.Where(nv => nv.Name == propertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", propertyPath); if (exactMatches.Count() == 1) { instance.Add(this.MultiValuePropertyEmptyOrNull(memberProperty, exactMatches.Single().Value)); } }
/// <summary> /// Visits a collection of parameters. /// </summary> /// <param name="parameters">The parameters to visit.</param> protected override ODataPayloadElement VisitParameters(ODataParameters parameters) { ExceptionUtilities.CheckArgumentNotNull(parameters, "parameters"); ComplexInstance result = new ComplexInstance(); result.IsNull = parameters.Count == 0; foreach (var parameter in parameters) { if (parameter.Value == null) { result.Add(new PrimitiveProperty(parameter.Key, null, null)); continue; } ODataCollectionStart odataCollectionStart = parameter.Value as ODataCollectionStart; if (odataCollectionStart != null) { ODataCollectionItemsObjectModelAnnotation annotation = odataCollectionStart.GetAnnotation <ODataCollectionItemsObjectModelAnnotation>(); PrimitiveMultiValue primitiveCollection = PayloadBuilder.PrimitiveMultiValue(); foreach (var value in annotation) { primitiveCollection.Item(value); } PrimitiveMultiValueProperty primitiveCollectionProperty = new PrimitiveMultiValueProperty(parameter.Key, primitiveCollection); result.Add(primitiveCollectionProperty); } else { result.Add(new PrimitiveProperty(parameter.Key, null, PayloadBuilder.PrimitiveValue(parameter.Value).ClrValue)); } } return(result); }
/// <summary> /// Visits a resource value item. /// </summary> /// <param name="resourceValue">The resource value to visit.</param> protected override ODataPayloadElement VisitResourceValue(ODataResourceValue resourceValue) { if (resourceValue == null) { return(new ComplexInstance(null, true)); } else { ComplexInstance complexElement = new ComplexInstance(resourceValue.TypeName, false); foreach (ODataProperty childProperty in resourceValue.Properties) { complexElement.Add((PropertyInstance)this.Visit(childProperty)); } this.ConvertSerializationTypeNameAnnotation(resourceValue, complexElement); return(complexElement); } }
private bool TryGetComplexInstance(JsonObject jsonObject, out ODataPayloadElement elem) { string typeName = this.GetMetadataPropertyValue(jsonObject, TypeFieldName); ComplexInstance complex = new ComplexInstance(typeName, false); elem = null; foreach (JsonProperty prop in jsonObject.Properties) { // Just parse the object properties. Skip properties like "__metadata", "Count" and "Next" if (prop.Name != MetadataFieldName) { complex.Add(this.ConvertProperty(prop) as PropertyInstance); } } elem = complex; return(elem != null); }
/// <summary> /// Converts a LinqNewExpression to a Complex Instance /// </summary> /// <param name="expression">Expression to convert to a ComplexInstance</param> /// <returns>Complex Instance</returns> internal static ComplexInstance ConvertToComplexInstance(this QueryExpression expression) { var nullConstantExpression = expression as QueryNullExpression; var queryComplexType = (QueryComplexType)expression.ExpressionType; if (nullConstantExpression != null) { return new ComplexInstance(queryComplexType.ComplexType.FullName, true); } var structuralExpression = expression as LinqNewInstanceExpression; var newComplexInstance = new ComplexInstance(queryComplexType.ComplexType.FullName, false); ExceptionUtilities.Assert(structuralExpression.MemberNames.Count == structuralExpression.Members.Count, "MemberNames and Members count are not equal"); for (int i = 0; i < structuralExpression.MemberNames.Count; i++) { string memberName = structuralExpression.MemberNames[i]; var memberExpression = structuralExpression.Members[i]; var memberProperty = queryComplexType.ComplexType.Properties.Single(p => p.Name == memberName); var complexDataType = memberProperty.PropertyType as ComplexDataType; var collectionDataType = memberProperty.PropertyType as CollectionDataType; if (complexDataType != null) { var childComplexInstance = memberExpression.ConvertToComplexInstance(); var complexProperty = new ComplexProperty() { Name = memberName, Value = childComplexInstance }; newComplexInstance.Add(complexProperty); } else if (collectionDataType != null) { var collectionPropertyType = memberProperty.PropertyType as CollectionDataType; var convertedValue = memberExpression.ConvertToMultiValue(collectionPropertyType.ElementDataType); if (collectionPropertyType.ElementDataType is ComplexDataType) { newComplexInstance.Add(new ComplexMultiValueProperty(memberName, convertedValue as ComplexMultiValue)); } else { var primitiveDataType = collectionPropertyType.ElementDataType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Not a primitiveDataType '{0}'", collectionPropertyType.ElementDataType); newComplexInstance.Add(new PrimitiveMultiValueProperty(memberName, convertedValue as PrimitiveMultiValue)); } } else { var primitiveDataType = memberProperty.PropertyType as PrimitiveDataType; ExceptionUtilities.CheckObjectNotNull(primitiveDataType, "Expected a PrimitiveDataType"); var primitiveValue = memberExpression.ConvertToPrimitiveValue(primitiveDataType); newComplexInstance.Add(new PrimitiveProperty(memberName, primitiveDataType.GetEdmTypeName(), primitiveValue.ClrValue)); } } return newComplexInstance; }
private void PopulatePropertiesFromObject(ComplexInstance instance, IEnumerable<MemberProperty> properties, object anonymous) { ExceptionUtilities.CheckArgumentNotNull(instance, "instance"); ExceptionUtilities.CheckArgumentNotNull(properties, "properties"); ExceptionUtilities.CheckArgumentNotNull(anonymous, "anonymous"); Type anonymousType = anonymous.GetType(); foreach (PropertyInfo info in anonymousType.GetProperties()) { object value = info.GetValue(anonymous, null); MemberProperty property = properties.SingleOrDefault(p => p.Name == info.Name); if (property == null) { instance.Add(this.DynamicProperty(info.Name, info.PropertyType, value)); } else if (property.PropertyType is ComplexDataType) { instance.Add(this.ComplexProperty(property, value)); } else if (property.PropertyType is CollectionDataType) { instance.Add(this.MultiValueProperty(property, value)); } else { instance.Add(this.PrimitiveProperty(property, value)); } } }
private void PopulateComplexMultiValuePropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues, ComplexDataType complexTypeElementDataType) { int i = 0; bool completed = false; var complexCollection = new ComplexMultiValueProperty(memberProperty.Name, new ComplexMultiValue(complexTypeElementDataType.BuildMultiValueTypeName(), false)); while (!completed) { IEnumerable<NamedValue> complexInstanceNamedValues = namedValues.Where(pp => pp.Name.StartsWith(propertyPath + "." + i + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() == 0) { completed = true; } else { ComplexInstance complexInstance = this.ComplexInstance(complexTypeElementDataType.Definition, propertyPath + "." + i, complexInstanceNamedValues); complexCollection.Value.Add(complexInstance); } i++; } if (i > 1) { instance.Add(complexCollection); } }
private void PopulatePrimitiveBagPropertyFromPaths(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues, PrimitiveDataType primitiveElementDataType) { int i = 0; bool completed = false; var primitiveCollection = new PrimitiveMultiValue(primitiveElementDataType.BuildMultiValueTypeName(), false); while (!completed) { IEnumerable<NamedValue> primitiveItemNamedValues = namedValues.Where(pp => pp.Name == propertyPath + "." + i).ToList(); if (primitiveItemNamedValues.Count() == 0) { completed = true; } else { ExceptionUtilities.Assert(primitiveItemNamedValues.Count() < 2, "Should not get more than one value for a primitive Bag item for path '{0}'", propertyPath + "." + i); var value = primitiveItemNamedValues.Single(); // Do something with the value primitiveCollection.Add(PrimitiveValue(primitiveElementDataType, value.Value)); } i++; } if (i > 1) { instance.Add(new PrimitiveMultiValueProperty(memberProperty.Name, primitiveCollection)); } }
/// <summary> /// Deserialize the element as a complex instance /// </summary> /// <param name="element">The xml representing a complex instance</param> /// <returns>The deserialized complex instance</returns> private ComplexInstance DeserializeComplexInstance(XElement element) { ComplexInstance instance = new ComplexInstance(); // get the type XAttribute type = element.Attribute(MetadataType); if (type != null) { instance.FullTypeName = type.Value; } // check for the null attribute XAttribute isNull = element.Attribute(MetadataNull); if (isNull != null) { instance.IsNull = bool.Parse(isNull.Value); } else if (element.HasElements) { instance.IsNull = false; } // get the properties foreach (XElement subElement in element.Elements()) { instance.Add(this.DeserializeProperty(subElement)); } return instance; }
private void PopulateCollectionPropertyWithNullOrEmpty(ComplexInstance instance, MemberProperty memberProperty, string propertyPath, IEnumerable<NamedValue> namedValues) { IEnumerable<NamedValue> exactMatches = namedValues.Where(nv => nv.Name == propertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", propertyPath); if (exactMatches.Count() == 1) { instance.Add(this.MultiValuePropertyEmptyOrNull(memberProperty, exactMatches.Single().Value)); } }
private void PopulatePropertiesFromPaths(ComplexInstance instance, IEnumerable<MemberProperty> properties, string propertyPath, IEnumerable<NamedValue> namedValues) { ExceptionUtilities.CheckArgumentNotNull(instance, "instance"); ExceptionUtilities.CheckArgumentNotNull(properties, "properties"); ExceptionUtilities.CheckArgumentNotNull(namedValues, "namedValues"); foreach (MemberProperty property in properties) { string childPropertyPath = property.Name; if (propertyPath != null) { childPropertyPath = propertyPath + "." + property.Name; } CollectionDataType collectionDataType = property.PropertyType as CollectionDataType; PrimitiveDataType primitiveDataType = property.PropertyType as PrimitiveDataType; if (primitiveDataType != null) { NamedValue memberPropertyNamedValue = namedValues.SingleOrDefault(nv => nv.Name == childPropertyPath); if (memberPropertyNamedValue != null) { instance.Add(this.PrimitiveProperty(property, memberPropertyNamedValue.Value)); } } else if (collectionDataType != null) { IEnumerable<NamedValue> bagNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (bagNamedValues.Count() > 0) { this.PopulateMultiValuePropertyFromPaths(instance, property, collectionDataType.ElementDataType, childPropertyPath, bagNamedValues); } else { this.PopulateCollectionPropertyWithNullOrEmpty(instance, property, childPropertyPath, namedValues); } } else { var complexDataType = property.PropertyType as ComplexDataType; ExceptionUtilities.CheckObjectNotNull(complexDataType, "Property '{0}' was not primitive, a collection, or complex", property.Name); IEnumerable<NamedValue> complexInstanceNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList(); if (complexInstanceNamedValues.Count() > 0) { PropertyInstance memberPropertyInstance = this.ComplexProperty(property, childPropertyPath, complexInstanceNamedValues); instance.Add(memberPropertyInstance); } else { // Check for null case IEnumerable<NamedValue> exactMatches = namedValues.Where(nv => nv.Name == childPropertyPath).ToList(); ExceptionUtilities.Assert(exactMatches.Count() < 2, "Should only find at most one property path {0} when looking for null value", childPropertyPath); if (exactMatches.Count() == 1) { instance.Add(new ComplexProperty(property.Name, new ComplexInstance(complexDataType.Definition.FullName, true))); } } } } }
/// <summary> /// Visits a collection of parameters. /// </summary> /// <param name="parameters">The parameters to visit.</param> protected override ODataPayloadElement VisitParameters(ODataParameters parameters) { ExceptionUtilities.CheckArgumentNotNull(parameters, "parameters"); ComplexInstance result = new ComplexInstance(); result.IsNull = parameters.Count == 0; foreach (var parameter in parameters) { if (parameter.Value == null) { result.Add(new PrimitiveProperty(parameter.Key, null, null)); continue; } ODataComplexValue odataComplexValue = parameter.Value as ODataComplexValue; ODataCollectionStart odataCollectionStart = parameter.Value as ODataCollectionStart; if (odataCollectionStart != null) { ODataCollectionItemsObjectModelAnnotation annotation = odataCollectionStart.GetAnnotation <ODataCollectionItemsObjectModelAnnotation>(); if (annotation.OfType <ODataComplexValue>().FirstOrDefault() != null) { ComplexMultiValue complexCollection = PayloadBuilder.ComplexMultiValue(); foreach (var value in annotation) { complexCollection.Item(this.VisitComplexValue(value as ODataComplexValue) as ComplexInstance); } ComplexMultiValueProperty complexCollectionProperty = new ComplexMultiValueProperty(parameter.Key, complexCollection); result.Add(complexCollectionProperty); } else { PrimitiveMultiValue primitiveCollection = PayloadBuilder.PrimitiveMultiValue(); foreach (var value in annotation) { primitiveCollection.Item(value); } PrimitiveMultiValueProperty primitiveCollectionProperty = new PrimitiveMultiValueProperty(parameter.Key, primitiveCollection); result.Add(primitiveCollectionProperty); } } else if (odataComplexValue != null) { ComplexInstance complexInstance = PayloadBuilder.ComplexValue(odataComplexValue.TypeName); complexInstance.IsNull = false; foreach (ODataProperty odataProperty in odataComplexValue.Properties) { complexInstance.Property(odataProperty.Name, this.Visit(odataProperty.Value)); } result.Add(new ComplexProperty(parameter.Key, complexInstance)); } else { result.Add(new PrimitiveProperty(parameter.Key, null, PayloadBuilder.PrimitiveValue(parameter.Value).ClrValue)); } } return(result); }
private static ODataPayloadElement CreatePayloadElement(IEdmModel model, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfig) { IEdmEntitySet citySet = model.EntityContainer.FindEntitySet("Cities"); IEdmEntityType cityType = model.EntityTypes().Single(e => e.Name == "CityType"); IEdmProperty cityNameProperty = cityType.Properties().Single(e => e.Name == "Name"); IEdmNavigationProperty policeStationNavProp = cityType.NavigationProperties().Single(e => e.Name == "PoliceStation"); IEdmOperationImport primitiveCollectionResultOperation = model.EntityContainer.FindOperationImports("PrimitiveCollectionResultOperation").Single(); IEdmOperationImport serviceOp1 = model.EntityContainer.FindOperationImports("ServiceOperation1").Single(); bool isRequest = testConfig.IsRequest; bool isJsonLightRequest = isRequest && testConfig.Format == ODataFormat.Json; switch (payloadKind) { case ODataPayloadKind.Feed: { return(PayloadBuilder.EntitySet().WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet)); } case ODataPayloadKind.Entry: { return(PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet)); } case ODataPayloadKind.Property: return(PayloadBuilder.PrimitiveProperty(isJsonLightRequest ? string.Empty : null, "SomeCityValue").ExpectedProperty(cityType, "Name")); case ODataPayloadKind.EntityReferenceLink: return(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink").ExpectedNavigationProperty(citySet, cityType, "PoliceStation")); case ODataPayloadKind.EntityReferenceLinks: return(PayloadBuilder.LinkCollection().Item(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink")).ExpectedNavigationProperty((EdmEntitySet)citySet, (EdmEntityType)cityType, "CityHall")); case ODataPayloadKind.Value: return(PayloadBuilder.PrimitiveValue("PrimitiveValue")); case ODataPayloadKind.BinaryValue: return(PayloadBuilder.PrimitiveValue(new byte[] { 0, 0, 1, 1 })); case ODataPayloadKind.Collection: return(PayloadBuilder.PrimitiveCollection().CollectionName(null).ExpectedFunctionImport((EdmOperationImport)primitiveCollectionResultOperation)); case ODataPayloadKind.ServiceDocument: Debug.Assert(!isRequest, "Not supported in requests."); return(new ServiceDocumentInstance().Workspace(PayloadBuilder.Workspace())); case ODataPayloadKind.MetadataDocument: Debug.Assert(!isRequest, "Not supported in requests."); throw new NotImplementedException(); case ODataPayloadKind.Error: Debug.Assert(!isRequest, "Not supported in requests."); return(PayloadBuilder.Error("ErrorCode")); case ODataPayloadKind.Parameter: // build parameter payload based on model definition var parameterPayload = new ComplexInstance(null, false); ODataPayloadElement a = PayloadBuilder.PrimitiveValue(123).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false)); ODataPayloadElement b = PayloadBuilder.PrimitiveValue("stringvalue").WithTypeAnnotation(EdmCoreModel.Instance.GetString(false)); PrimitiveProperty parametera = new PrimitiveProperty("a", "Edm.Integer", ((PrimitiveValue)a).ClrValue); PrimitiveProperty parameterb = new PrimitiveProperty("b", "Edm.String", ((PrimitiveValue)b).ClrValue); parameterPayload.Add(parametera); parameterPayload.Add(parameterb); parameterPayload.ExpectedFunctionImport((EdmOperationImport)serviceOp1); return(parameterPayload); case ODataPayloadKind.Unsupported: // fall through default: throw new NotSupportedException(); } }
/// <summary> /// Builds a complex instance from the given payloadElements to represent a parameters payload. /// </summary> /// <param name="payloadElements">Each ODataPayloadElement represents the value for each parameter.</param> /// <param name="model">EdmModel instance.</param> /// <param name="functionImportName">Name of the function import to add to the model.</param> /// <returns></returns> private static ComplexInstance PayloadElementsToParameterPayload(ODataPayloadElement[] payloadElements, EdmModel model, string functionImportName) { EdmOperationImport operationImport = (EdmOperationImport)model.EntityContainer.FindOperationImports(functionImportName).FirstOrDefault(); EdmOperation operation = (EdmOperation)operationImport.Operation; var parameterPayload = new ComplexInstance(null, false); for (int idx = 0; idx < payloadElements.Length; idx++) { ODataPayloadElement p = payloadElements[idx]; string parameterName = "p" + idx; PropertyInstance parameter; IEdmTypeReference entityModelType = p.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType; switch (p.ElementType) { case ODataPayloadElementType.PrimitiveValue: object clrValue = ((PrimitiveValue)p).ClrValue; PrimitiveValue primitiveValue = new PrimitiveValue(clrValue == null ? null : clrValue.GetType().FullName, clrValue); primitiveValue.CopyAnnotation <PrimitiveValue, EntityModelTypeAnnotation>(p); parameter = new PrimitiveProperty(parameterName, primitiveValue); operation.AddParameter(parameterName, MetadataUtils.GetPrimitiveTypeReference(primitiveValue.ClrValue.GetType())); break; case ODataPayloadElementType.ComplexInstance: parameter = new ComplexProperty(parameterName, (ComplexInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.PrimitiveMultiValue: PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)p; if (primitiveMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { primitiveMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new PrimitiveMultiValueProperty(parameterName, primitiveMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.ComplexMultiValue: ComplexMultiValue complexMultiValue = (ComplexMultiValue)p; if (complexMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { complexMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new ComplexMultiValueProperty(parameterName, complexMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntityInstance: parameter = new NavigationPropertyInstance(parameterName, (EntityInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntitySetInstance: parameter = new NavigationPropertyInstance(parameterName, (EntitySetInstance)p); operation.AddParameter(parameterName, entityModelType); break; default: throw new NotSupportedException("PayloadElementsToParameterPayload() is called on unsupported ODataPayloadElement type: " + p.ElementType); } parameterPayload.Add(parameter); } parameterPayload.ExpectedFunctionImport(operationImport); return(parameterPayload); }
private static ODataPayloadElement CreatePayloadElement(IEdmModel model, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfig) { IEdmEntitySet citySet = model.EntityContainer.FindEntitySet("Cities"); IEdmEntityType cityType = model.EntityTypes().Single(e => e.Name == "CityType"); IEdmProperty cityNameProperty = cityType.Properties().Single(e => e.Name == "Name"); IEdmNavigationProperty policeStationNavProp = cityType.NavigationProperties().Single(e => e.Name == "PoliceStation"); IEdmOperationImport primitiveCollectionResultOperation = model.EntityContainer.FindOperationImports("PrimitiveCollectionResultOperation").Single(); IEdmOperationImport serviceOp1 = model.EntityContainer.FindOperationImports("ServiceOperation1").Single(); bool isRequest = testConfig.IsRequest; bool isJsonLightRequest = isRequest && testConfig.Format == ODataFormat.Json; switch (payloadKind) { case ODataPayloadKind.Feed: { return PayloadBuilder.EntitySet().WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet); } case ODataPayloadKind.Entry: { return PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet); } case ODataPayloadKind.Property: return PayloadBuilder.PrimitiveProperty(isJsonLightRequest ? string.Empty : null, "SomeCityValue").ExpectedProperty(cityType, "Name"); case ODataPayloadKind.EntityReferenceLink: return PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink").ExpectedNavigationProperty(citySet, cityType, "PoliceStation"); case ODataPayloadKind.EntityReferenceLinks: return PayloadBuilder.LinkCollection().Item(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink")).ExpectedNavigationProperty((EdmEntitySet)citySet, (EdmEntityType)cityType, "CityHall"); case ODataPayloadKind.Value: return PayloadBuilder.PrimitiveValue("PrimitiveValue"); case ODataPayloadKind.BinaryValue: return PayloadBuilder.PrimitiveValue(new byte[] { 0, 0, 1, 1 }); case ODataPayloadKind.Collection: return PayloadBuilder.PrimitiveCollection().CollectionName(null).ExpectedFunctionImport((EdmOperationImport)primitiveCollectionResultOperation); case ODataPayloadKind.ServiceDocument: Debug.Assert(!isRequest, "Not supported in requests."); return new ServiceDocumentInstance().Workspace(PayloadBuilder.Workspace()); case ODataPayloadKind.MetadataDocument: Debug.Assert(!isRequest, "Not supported in requests."); throw new NotImplementedException(); case ODataPayloadKind.Error: Debug.Assert(!isRequest, "Not supported in requests."); return PayloadBuilder.Error("ErrorCode"); case ODataPayloadKind.Parameter: // build parameter payload based on model definition var parameterPayload = new ComplexInstance(null, false); ODataPayloadElement a = PayloadBuilder.PrimitiveValue(123).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false)); ODataPayloadElement b = PayloadBuilder.PrimitiveValue("stringvalue").WithTypeAnnotation(EdmCoreModel.Instance.GetString(false)); PrimitiveProperty parametera = new PrimitiveProperty("a", "Edm.Integer", ((PrimitiveValue)a).ClrValue); PrimitiveProperty parameterb = new PrimitiveProperty("b", "Edm.String", ((PrimitiveValue)b).ClrValue); parameterPayload.Add(parametera); parameterPayload.Add(parameterb); parameterPayload.ExpectedFunctionImport((EdmOperationImport)serviceOp1); return parameterPayload; case ODataPayloadKind.Unsupported: // fall through default: throw new NotSupportedException(); } }
/// <summary> /// Builds a complex instance from the given payloadElements to represent a parameters payload. /// </summary> /// <param name="payloadElements">Each ODataPayloadElement represents the value for each parameter.</param> /// <param name="model">EdmModel instance.</param> /// <param name="functionImportName">Name of the function import to add to the model.</param> /// <returns></returns> private static ComplexInstance PayloadElementsToParameterPayload(ODataPayloadElement[] payloadElements, EdmModel model, string functionImportName) { EdmOperationImport operationImport = (EdmOperationImport)model.EntityContainer.FindOperationImports(functionImportName).FirstOrDefault(); EdmOperation operation = (EdmOperation)operationImport.Operation; var parameterPayload = new ComplexInstance(null, false); for (int idx = 0; idx < payloadElements.Length; idx++) { ODataPayloadElement p = payloadElements[idx]; string parameterName = "p" + idx; PropertyInstance parameter; IEdmTypeReference entityModelType = p.GetAnnotation<EntityModelTypeAnnotation>().EdmModelType; switch (p.ElementType) { case ODataPayloadElementType.PrimitiveValue: object clrValue = ((PrimitiveValue)p).ClrValue; PrimitiveValue primitiveValue = new PrimitiveValue(clrValue == null ? null : clrValue.GetType().FullName, clrValue); primitiveValue.CopyAnnotation<PrimitiveValue, EntityModelTypeAnnotation>(p); parameter = new PrimitiveProperty(parameterName, primitiveValue); operation.AddParameter(parameterName, MetadataUtils.GetPrimitiveTypeReference(primitiveValue.ClrValue.GetType())); break; case ODataPayloadElementType.ComplexInstance: parameter = new ComplexProperty(parameterName, (ComplexInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.PrimitiveMultiValue: PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)p; if (primitiveMultiValue.Annotations.OfType<JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { primitiveMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new PrimitiveMultiValueProperty(parameterName, primitiveMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.ComplexMultiValue: ComplexMultiValue complexMultiValue = (ComplexMultiValue)p; if (complexMultiValue.Annotations.OfType<JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { complexMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new ComplexMultiValueProperty(parameterName, complexMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntityInstance: parameter = new NavigationPropertyInstance(parameterName, (EntityInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntitySetInstance: parameter = new NavigationPropertyInstance(parameterName, (EntitySetInstance)p); operation.AddParameter(parameterName, entityModelType); break; default: throw new NotSupportedException("PayloadElementsToParameterPayload() is called on unsupported ODataPayloadElement type: " + p.ElementType); } parameterPayload.Add(parameter); } parameterPayload.ExpectedFunctionImport(operationImport); return parameterPayload; }