예제 #1
0
        /// <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>());
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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);
            }
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        /// <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());
        }
예제 #9
0
 /// <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()));
 }
예제 #10
0
        private static bool IsStringPayloadValueAndTypeBinary(object value, IEdmTypeReference edmTypeReference)
        {
            IEdmPrimitiveTypeReference actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType());

            return(actualTypeReference.IsString() && edmTypeReference.IsBinary());
        }
예제 #11
0
        /// <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());
        }
예제 #12
0
 /// <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());
 }
예제 #13
0
        internal static void ValidateIsExpectedPrimitiveType(object value, IEdmTypeReference expectedTypeReference)
        {
            IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType());

            ValidateIsExpectedPrimitiveType(value, primitiveTypeReference, expectedTypeReference);
        }