/// <summary> /// Writes a primitive value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="collectionValidator">The collection validator instance.</param> /// <param name="expectedTypeReference">The expected type of the primitive value.</param> internal void WritePrimitiveValue( object value, CollectionWithoutExpectedTypeValidator collectionValidator, IEdmTypeReference expectedTypeReference) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(value != null, "value != null"); IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(o.Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } string typeName = primitiveTypeReference.FullName(); if (collectionValidator != null) { collectionValidator.ValidateCollectionItem(typeName, EdmTypeKind.Primitive); if (string.CompareOrdinal(collectionValidator.ItemTypeNameFromCollection, typeName) == 0) { typeName = null; } } if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, primitiveTypeReference, expectedTypeReference); } if (typeName != null && typeName != Metadata.EdmConstants.EdmStringTypeName) { this.WritePropertyTypeAttribute(typeName); } AtomValueUtils.WritePrimitiveValue(this.XmlWriter, value); }
/// <summary> /// Writes the value of a primitive instance annotation. /// </summary> /// <param name="primitiveValue">The primitive value to write.</param> /// <param name="expectedTypeReference">The expected type of the annotation from the metadata.</param> private void WritePrimitiveInstanceAnnotationValue(ODataPrimitiveValue primitiveValue, IEdmTypeReference expectedTypeReference) { object clrValue = primitiveValue.Value; IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(clrValue.GetType()); string attributeValueNotationName = AtomInstanceAnnotation.LookupAttributeValueNotationNameByEdmTypeKind(primitiveTypeReference.PrimitiveKind()); // Some primitive values can be specified more concisely via an attribute rather than in the content of the xml element. This is called "attribute value notation". // If we're writing a type that supports this, then we always prefer attribute value notation over writing the value in the element content. if (attributeValueNotationName != null) { if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(primitiveValue.Value, primitiveTypeReference, expectedTypeReference); } this.XmlWriter.WriteAttributeString(attributeValueNotationName, AtomValueUtils.ConvertPrimitiveToString(clrValue)); } else { this.WritePrimitiveValue(clrValue, /*collectionValidator*/ null, expectedTypeReference, primitiveValue.GetAnnotation <SerializationTypeNameAnnotation>()); } }
/// <summary> /// Writes a primitive value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="collectionValidator">The collection validator instance.</param> /// <param name="expectedTypeReference">The expected type of the primitive value.</param> /// <param name="typeNameAnnotation">The optional type name annotation provided by the user on the OM for this primitive value. The annotation value will override whatever type name is being written.</param> internal void WritePrimitiveValue( object value, CollectionWithoutExpectedTypeValidator collectionValidator, IEdmTypeReference expectedTypeReference, SerializationTypeNameAnnotation typeNameAnnotation) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(value != null, "value != null"); IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(ODataErrorStrings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } if (collectionValidator != null) { collectionValidator.ValidateCollectionItem(primitiveTypeReference.FullName(), EdmTypeKind.Primitive); } if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, primitiveTypeReference, expectedTypeReference); } string collectionItemTypeName; string typeName = this.AtomOutputContext.TypeNameOracle.GetValueTypeNameForWriting(value, primitiveTypeReference, typeNameAnnotation, collectionValidator, out collectionItemTypeName); Debug.Assert(collectionItemTypeName == null, "collectionItemTypeName == null"); if (typeName != null && typeName != EdmConstants.EdmStringTypeName) { this.WritePropertyTypeAttribute(typeName); } AtomValueUtils.WritePrimitiveValue(this.XmlWriter, value); }
/// <summary> /// Writes a primitive value. /// Uses a registered primitive type converter to write the value if one is registered for the type, otherwise directly writes the value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="expectedTypeReference">The expected type reference of the primitive value.</param> public void WritePrimitiveValue( object value, IEdmTypeReference expectedTypeReference) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(value != null, "value != null"); IEdmPrimitiveTypeReference actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, actualTypeReference, expectedTypeReference); } if (actualTypeReference != null && actualTypeReference.IsSpatial()) { PrimitiveConverter.Instance.WriteJsonLight(value, this.JsonWriter, this.Version); } else { this.JsonWriter.WritePrimitiveValue(value, this.Version); } }
/// <summary> /// Asynchronously writes a primitive value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="actualTypeReference">The actual type reference of the primitive value.</param> /// <param name="expectedTypeReference">The expected type reference of the primitive value.</param> /// <returns>A task that represents the asynchronous write operation.</returns> public virtual async Task WritePrimitiveValueAsync( object value, IEdmTypeReference actualTypeReference, IEdmTypeReference expectedTypeReference) { Debug.Assert(value != null, "value != null"); if (actualTypeReference == null) { // Try convert primitive values from their actual CLR types to their underlying CLR types. value = this.Model.ConvertToUnderlyingTypeIfUIntValue(value, expectedTypeReference); actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); } ODataPayloadValueConverter converter = this.JsonLightOutputContext.PayloadValueConverter; // Skip validation if user has set custom PayloadValueConverter if (expectedTypeReference != null && converter.GetType() == typeof(ODataPayloadValueConverter)) { this.WriterValidator.ValidateIsExpectedPrimitiveType(value, (IEdmPrimitiveTypeReference)actualTypeReference, expectedTypeReference); } value = converter.ConvertToPayloadValue(value, expectedTypeReference); if (actualTypeReference != null && actualTypeReference.IsSpatial()) { // TODO: Implement asynchronous handling of spatial types in a separate PR await TaskUtils.GetTaskForSynchronousOperation(() => { PrimitiveConverter.Instance.WriteJsonLight(value, this.JsonWriter); }).ConfigureAwait(false); } else { await this.AsynchronousJsonWriter.WritePrimitiveValueAsync(value).ConfigureAwait(false); } }
/// <summary> /// Writes a primitive value. /// Uses a registered primitive type converter to write the value if one is registered for the type, otherwise directly writes the value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="collectionValidator">The collection validator instance.</param> /// <param name="expectedTypeReference">The expected type reference of the primitive value.</param> internal void WritePrimitiveValue( object value, CollectionWithoutExpectedTypeValidator collectionValidator, IEdmTypeReference expectedTypeReference) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(value != null, "value != null"); IEdmPrimitiveTypeReference actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (collectionValidator != null) { if (actualTypeReference == null) { throw new ODataException(o.Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } collectionValidator.ValidateCollectionItem(actualTypeReference.FullName(), EdmTypeKind.Primitive); } if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, actualTypeReference, expectedTypeReference); } if (actualTypeReference != null && actualTypeReference.IsSpatial()) { // For spatial types, we will always write the type name. This is consistent with complex types. string typeName = actualTypeReference.FullName(); PrimitiveConverter.Instance.WriteJson(value, this.JsonWriter, typeName, this.Version); } else { this.JsonWriter.WritePrimitiveValue(value, this.Version); } }
/// <summary> /// Validates that a given primitive value is of the expected (primitive) type. /// </summary> /// <param name="value">The value to check.</param> /// <param name="valuePrimitiveTypeReference">The primitive type reference for the value - some callers have this already, so we save the lookup here.</param> /// <param name="expectedTypeReference">The expected type for the value.</param> /// <param name="bypassValidation">Bypass the validation if it is true.</param> /// <remarks> /// Some callers have the primitive type reference already resolved (from the value type) /// so this method is an optimized version to not lookup the primitive type reference again. /// </remarks> internal static void ValidateIsExpectedPrimitiveType(object value, IEdmPrimitiveTypeReference valuePrimitiveTypeReference, IEdmTypeReference expectedTypeReference, bool bypassValidation = false) { Debug.Assert(value != null, "value != null"); Debug.Assert(expectedTypeReference != null, "expectedTypeReference != null"); if (bypassValidation) { return; } if (valuePrimitiveTypeReference == null) { throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } Debug.Assert(valuePrimitiveTypeReference.IsEquivalentTo(EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType())), "The value and valuePrimitiveTypeReference don't match."); if (!expectedTypeReference.IsODataPrimitiveTypeKind() && !expectedTypeReference.IsODataTypeDefinitionTypeKind()) { // non-primitive type found for primitive value. throw new ODataException(Strings.ValidationUtils_NonPrimitiveTypeForPrimitiveValue(expectedTypeReference.ODataFullName())); } ValidateMetadataPrimitiveType(expectedTypeReference, valuePrimitiveTypeReference); }
/// <summary> /// Gets the type name based on the given odata value. /// </summary> /// <param name="value">The value.</param> /// <param name="model">The model used to handle unsigned int conversions.</param> /// <returns>The type name for the context URI.</returns> private static string GetTypeNameForValue(ODataValue value, IEdmModel model) { if (value == null) { return(null); } // special identifier for null values. if (value.IsNullValue) { return(ODataConstants.ContextUriFragmentNull); } if (value.TypeAnnotation != null && !string.IsNullOrEmpty(value.TypeAnnotation.TypeName)) { return(value.TypeAnnotation.TypeName); } var collectionValue = value as ODataCollectionValue; if (collectionValue != null) { return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName)); } var enumValue = value as ODataEnumValue; if (enumValue != null) { return(enumValue.TypeName); } var resourceValue = value as ODataResourceValue; if (resourceValue != null) { return(resourceValue.TypeName); } var untypedValue = value as ODataUntypedValue; if (untypedValue != null) { return(ODataConstants.ContextUriFragmentUntyped); } ODataPrimitiveValue primitive = value as ODataPrimitiveValue; if (primitive == null) { Debug.Assert(value is ODataStreamReferenceValue, "value is ODataStreamReferenceValue"); throw new ODataException(Strings.ODataContextUriBuilder_StreamValueMustBePropertiesOfODataResource); } // Try convert to underlying type if the primitive value is unsigned int. IEdmTypeDefinitionReference typeDefinitionReference = model.ResolveUIntTypeDefinition(primitive.Value); if (typeDefinitionReference != null) { return(typeDefinitionReference.FullName()); } IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitive.Value.GetType()); return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.FullName()); }
/// <summary> /// Resolve a primitive value type name /// </summary> /// <param name="primitiveValue">The value to get the type name from.</param> /// <returns>A type for primitive value</returns> internal static IEdmTypeReference ResolveAndValidateTypeForPrimitiveValue(ODataPrimitiveValue primitiveValue) { return(EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType())); }
private static bool IsStringPayloadValueAndTypeBinary(object value, IEdmTypeReference edmTypeReference) { IEdmPrimitiveTypeReference actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); return(actualTypeReference.IsString() && edmTypeReference.IsBinary()); }
/// <summary> /// Gets the type name from the given <paramref name="value"/>. /// </summary> /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataCollectionValue or a Clr primitive object.</param> /// <returns>The type name for the given <paramref name="value"/>.</returns> protected static string GetTypeNameFromValue(object value) { Debug.Assert(value != null, "value != null"); ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue; if (primitiveValue != null) { // primitiveValueTypeReference == null means: the EDM type of the primitive value cannot be determined. // This could possibly be due to value being an unsigned int. // In this case, simply return null because: // - If the property is regular property, the type is not needed since service model knows its exact type. // - If the property is dynamic property, ODL does not support dynamic property containing unsigned int value // since we don't know its underlying type as well as how to serialize it. IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()); return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.FullName()); } ODataEnumValue enumValue = value as ODataEnumValue; if (enumValue != null) { return(enumValue.TypeName); } ODataResourceValue resourceValue = value as ODataResourceValue; if (resourceValue != null) { return(resourceValue.TypeName); } ODataCollectionValue collectionValue = value as ODataCollectionValue; if (collectionValue != null) { return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName)); } ODataBinaryStreamValue binaryStreamValue = value as ODataBinaryStreamValue; if (binaryStreamValue != null) { return(EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Binary, true).FullName()); } ODataStreamReferenceValue streamValue = value as ODataStreamReferenceValue; if (streamValue != null) { return(EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Stream, true).FullName()); } IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } return(primitiveTypeReference.FullName()); }
/// <summary> /// Create a ConstantNode /// </summary> /// <param name="constantValue">This node's primitive value.</param> public ConstantNode(object constantValue) { this.constantValue = constantValue; this.typeReference = constantValue == null ? null : EdmLibraryExtensions.GetPrimitiveTypeReference(constantValue.GetType()); }
internal static void ValidateIsExpectedPrimitiveType(object value, IEdmTypeReference expectedTypeReference) { IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); ValidateIsExpectedPrimitiveType(value, primitiveTypeReference, expectedTypeReference); }