Ejemplo n.º 1
0
        private ODataStreamReferenceValue ReadStreamPropertyValue()
        {
            if (!base.ReadingResponse)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_StreamPropertyInRequest);
            }
            ODataVersionChecker.CheckStreamReferenceProperty(base.Version);
            base.JsonReader.ReadStartObject();
            ODataStreamReferenceValue value2 = null;

            if (base.JsonReader.NodeType != JsonNodeType.Property)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_CannotParseStreamReference);
            }
            string strB = base.JsonReader.ReadPropertyName();

            if (string.CompareOrdinal("__mediaresource", strB) != 0)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_CannotParseStreamReference);
            }
            value2 = this.ReadStreamReferenceValue();
            if (base.JsonReader.NodeType != JsonNodeType.EndObject)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_CannotParseStreamReference);
            }
            base.JsonReader.Read();
            return(value2);
        }
Ejemplo n.º 2
0
        public static object ConvertFromUriLiteral(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
        {
            Exception       exception;
            ExpressionToken token;

            ExceptionUtils.CheckArgumentNotNull <string>(value, "value");
            if ((typeReference != null) && (model == null))
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeRefWithoutModel);
            }
            if (model == null)
            {
                model = EdmCoreModel.Instance;
            }
            ExpressionLexer lexer = new ExpressionLexer(value, false);

            if (!lexer.TryPeekNextToken(out token, out exception))
            {
                return(ODataUriConversionUtils.ConvertFromComplexOrCollectionValue(value, version, model, typeReference));
            }
            object primitiveValue = lexer.ReadLiteralToken();

            if (typeReference != null)
            {
                primitiveValue = ODataUriConversionUtils.VerifyAndCoerceUriPrimitiveLiteral(primitiveValue, model, typeReference, version);
            }
            if (primitiveValue is ISpatial)
            {
                ODataVersionChecker.CheckSpatialValue(version);
            }
            return(primitiveValue);
        }
Ejemplo n.º 3
0
        private ISpatial ReadSpatialValue(IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue)
        {
            ODataVersionChecker.CheckSpatialValue(base.Version);
            if (this.TryReadNullValue(expectedValueTypeReference, validateNullValue))
            {
                return(null);
            }
            ISpatial spatial = null;

            if (base.JsonReader.NodeType == JsonNodeType.StartObject)
            {
                IDictionary <string, object> source    = this.ReadObjectValue(base.JsonReader);
                GeoJsonObjectFormatter       formatter = SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter();
                if (expectedValueTypeReference.IsGeographyType())
                {
                    spatial = formatter.Read <Geography>(source);
                }
                else
                {
                    spatial = formatter.Read <Geometry>(source);
                }
            }
            if (spatial == null)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_CannotReadSpatialPropertyValue);
            }
            return(spatial);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Verifies that the given <paramref name="primitiveValue"/> is or can be coerced to <paramref name="expectedTypeReference"/>, and coerces it if necessary.
        /// </summary>
        /// <param name="primitiveValue">An EDM primitive value to verify.</param>
        /// <param name="model">Model to verify against.</param>
        /// <param name="expectedTypeReference">Expected type reference.</param>
        /// <param name="version">The version to use for reading.</param>
        /// <returns>Coerced version of the <paramref name="primitiveValue"/>.</returns>
        internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(primitiveValue, "primitiveValue");
            ExceptionUtils.CheckArgumentNotNull(model, "model");
            ExceptionUtils.CheckArgumentNotNull(expectedTypeReference, "expectedTypeReference");

            // First deal with null literal
            ODataUriNullValue nullValue = primitiveValue as ODataUriNullValue;

            if (nullValue != null)
            {
                if (!expectedTypeReference.IsNullable)
                {
                    throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName()));
                }

                IEdmType actualResolvedType = ValidationUtils.ValidateValueTypeName(model, nullValue.TypeName, expectedTypeReference.Definition.TypeKind);
                Debug.Assert(actualResolvedType != null, "This is a primitive-only codepath so actualResolvedType != null.");

                if (actualResolvedType.IsSpatial())
                {
                    ODataVersionChecker.CheckSpatialValue(version);
                }

                if (TypePromotionUtils.CanConvertTo(actualResolvedType.ToTypeReference(), expectedTypeReference))
                {
                    nullValue.TypeName = expectedTypeReference.ODataFullName();
                    return(nullValue);
                }

                throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), nullValue.TypeName));
            }

            // Only other positive case is a numeric primitive that needs to be coerced
            IEdmPrimitiveTypeReference expectedPrimitiveTypeReference = expectedTypeReference.AsPrimitiveOrNull();

            if (expectedPrimitiveTypeReference == null)
            {
                throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue));
            }

            object coercedResult = CoerceNumericType(primitiveValue, expectedPrimitiveTypeReference.PrimitiveDefinition());

            if (coercedResult != null)
            {
                return(coercedResult);
            }

            Type actualType = primitiveValue.GetType();
            Type targetType = TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(expectedPrimitiveTypeReference));

            // If target type is assignable from actual type, we're OK
            if (targetType.IsAssignableFrom(actualType))
            {
                return(primitiveValue);
            }

            throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedPrimitiveTypeReference.ODataFullName(), primitiveValue));
        }
 private void WriteProperty(ODataProperty property, IEdmStructuredType owningType, bool allowStreamProperty, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties)
 {
     WriterValidationUtils.ValidatePropertyNotNull(property);
     if (!projectedProperties.ShouldSkipProperty(property.Name))
     {
         WriterValidationUtils.ValidateProperty(property);
         duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
         IEdmProperty expectedProperty = WriterValidationUtils.ValidatePropertyDefined(property.Name, owningType);
         if (((expectedProperty != null) && expectedProperty.Type.IsSpatial()) || ((expectedProperty == null) && (property.Value is ISpatial)))
         {
             ODataVersionChecker.CheckSpatialValue(base.Version);
         }
         base.JsonWriter.WriteName(property.Name);
         object obj2 = property.Value;
         if (obj2 == null)
         {
             WriterValidationUtils.ValidateNullPropertyValue(expectedProperty, base.MessageWriterSettings.WriterBehavior, base.Model);
             base.JsonWriter.WriteValue((string)null);
         }
         else
         {
             bool isOpenPropertyType = ((owningType != null) && owningType.IsOpen) && (expectedProperty == null);
             if (isOpenPropertyType)
             {
                 ValidationUtils.ValidateOpenPropertyValue(property.Name, obj2);
             }
             IEdmTypeReference propertyTypeReference = (expectedProperty == null) ? null : expectedProperty.Type;
             ODataComplexValue complexValue          = obj2 as ODataComplexValue;
             if (complexValue != null)
             {
                 this.WriteComplexValue(complexValue, propertyTypeReference, isOpenPropertyType, base.CreateDuplicatePropertyNamesChecker(), null);
             }
             else
             {
                 ODataCollectionValue collectionValue = obj2 as ODataCollectionValue;
                 if (collectionValue != null)
                 {
                     ODataVersionChecker.CheckCollectionValueProperties(base.Version, property.Name);
                     this.WriteCollectionValue(collectionValue, propertyTypeReference, isOpenPropertyType);
                 }
                 else if (obj2 is ODataStreamReferenceValue)
                 {
                     if (!allowStreamProperty)
                     {
                         throw new ODataException(Microsoft.Data.OData.Strings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(property.Name));
                     }
                     WriterValidationUtils.ValidateStreamReferenceProperty(property, expectedProperty, base.Version, base.WritingResponse);
                     this.WriteStreamReferenceValue((ODataStreamReferenceValue)property.Value);
                 }
                 else
                 {
                     this.WritePrimitiveValue(obj2, null, propertyTypeReference);
                 }
             }
         }
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Converts a <see cref="ODataCollectionValue"/> to a string for use in a Url.
        /// </summary>
        /// <param name="collectionValue">Instance to convert.</param>
        /// <param name="model">Model to be used for validation. User model is optional. The EdmLib core model is expected as a minimum.</param>
        /// <param name="version">Version to be compliant with. Collection requires >= V3.</param>
        /// <param name="format">ODataFormat to use for the format of the literal.</param>
        /// <returns>A string representation of <paramref name="collectionValue"/> to be added to a Url.</returns>
        internal static string ConvertToUriCollectionLiteral(ODataCollectionValue collectionValue, IEdmModel model, ODataVersion version, ODataFormat format)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(collectionValue, "collectionValue");
            ExceptionUtils.CheckArgumentNotNull(model, "model");

            ODataVersionChecker.CheckCollectionValue(version);

            StringBuilder builder = new StringBuilder();

            using (TextWriter textWriter = new StringWriter(builder, CultureInfo.InvariantCulture))
            {
                ODataMessageWriterSettings messageWriterSettings = new ODataMessageWriterSettings()
                {
                    Version = version,
                    Indent  = false
                };

                if (format == ODataFormat.VerboseJson)
                {
                    WriteJsonVerboseLiteral(
                        model,
                        messageWriterSettings,
                        textWriter,
                        (serializer) => serializer.WriteCollectionValue(
                            collectionValue,
                            null /*metadataTypeReference*/,
                            false /*isOpenPropertyType*/));
                }
                else if (format == ODataFormat.Json)
                {
                    WriteJsonLightLiteral(
                        model,
                        messageWriterSettings,
                        textWriter,
                        (serializer) => serializer.WriteCollectionValue(
                            collectionValue,
                            null /*metadataTypeReference*/,
                            false /*isTopLevelProperty*/,
                            true /*isInUri*/,
                            false /*isOpenPropertyType*/));
                }
                else
                {
                    throw new ArgumentException(ODataErrorStrings.ODataUriUtils_ConvertToUriLiteralUnsupportedFormat(format.ToString()));
                }
            }

            return(builder.ToString());
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Writes a name/value pair for a property.
        /// </summary>
        /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="metadata">The metadata provider to use or null if no metadata is available.</param>
        /// <param name="property">The property to write out.</param>
        /// <param name="owningType">The type owning the property (or null if no metadata is available).</param>
        /// <param name="version">The protocol version used for writing.</param>
        private static void WriteProperty(
            JsonWriter jsonWriter,
            DataServiceMetadataProviderWrapper metadata,
            ODataProperty property,
            ResourceType owningType,
            ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(jsonWriter != null, "jsonWriter != null");

            ValidationUtils.ValidateProperty(property);
            ResourceProperty resourceProperty   = ValidationUtils.ValidatePropertyDefined(property.Name, owningType);
            bool             isOpenPropertyType = owningType != null && owningType.IsOpenType && resourceProperty == null;

            jsonWriter.WriteName(property.Name);
            object value = property.Value;

            if (value == null)
            {
                // verify that MultiValue properties are not null
                if (resourceProperty != null && resourceProperty.Kind == ResourcePropertyKind.MultiValue)
                {
                    throw new ODataException(Strings.ODataWriter_MultiValuePropertiesMustNotHaveNullValue(resourceProperty.Name));
                }

                jsonWriter.WriteValue(null);
            }
            else
            {
                ResourceType      resourcePropertyType = resourceProperty == null ? null : resourceProperty.ResourceType;
                ODataComplexValue complexValue         = value as ODataComplexValue;
                if (complexValue != null)
                {
                    WriteComplexValue(jsonWriter, metadata, complexValue, resourcePropertyType, isOpenPropertyType, version);
                }
                else
                {
                    ODataMultiValue multiValue = value as ODataMultiValue;
                    if (multiValue != null)
                    {
                        ODataVersionChecker.CheckMultiValueProperties(version, property.Name);
                        WriteMultiValue(jsonWriter, metadata, multiValue, resourcePropertyType, isOpenPropertyType, version);
                    }
                    else
                    {
                        WritePrimitiveValue(jsonWriter, value, resourcePropertyType);
                    }
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Try and parse spatial type from the json payload.
        /// </summary>
        /// <param name="jsonReader">The JSON reader to read from.</param>
        /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object
        ///     (or the second property if the first one was odata.type).</param>
        /// <param name="inputContext">The input context with all the settings.</param>
        /// <param name="expectedValueTypeReference">Expected edm property type.</param>
        /// <param name="validateNullValue">true to validate null values; otherwise false.</param>
        /// <param name="recursionDepth">The recursion depth to start with.</param>
        /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param>
        /// <returns>An instance of the spatial type.</returns>
        internal static ISpatial ReadSpatialValue(
            BufferingJsonReader jsonReader,
            bool insideJsonObjectValue,
            ODataInputContext inputContext,
            IEdmPrimitiveTypeReference expectedValueTypeReference,
            bool validateNullValue,
            int recursionDepth,
            string propertyName)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(inputContext != null, "inputContext != null");
            Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null");
            Debug.Assert(expectedValueTypeReference.IsSpatial(), "TryParseSpatialType must be called only with spatial types");

            // Note that we made sure that payload type detection will not return spatial for <V3 payloads
            // So the only way we can get a spatial type reference is if it comes from the model,
            // in which case we want to fail for <V3 payloads, since we can't report spatial values from such payloads.
            ODataVersionChecker.CheckSpatialValue(inputContext.Version);

            // Spatial value can be either null constant or a JSON object
            // If it's a null primitive value, report a null value.
            if (!insideJsonObjectValue && TryReadNullValue(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName))
            {
                return(null);
            }

            System.Spatial.ISpatial spatialValue = null;
            if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject)
            {
                IDictionary <string, object>          jsonObject          = ReadObjectValue(jsonReader, insideJsonObjectValue, inputContext, recursionDepth);
                System.Spatial.GeoJsonObjectFormatter jsonObjectFormatter =
                    System.Spatial.SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter();
                if (EdmLibraryExtensions.IsGeographyType(expectedValueTypeReference))
                {
                    spatialValue = jsonObjectFormatter.Read <System.Spatial.Geography>(jsonObject);
                }
                else
                {
                    spatialValue = jsonObjectFormatter.Read <System.Spatial.Geometry>(jsonObject);
                }
            }

            if (spatialValue == null)
            {
                throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue);
            }

            return(spatialValue);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Writes a property with a collection value in ATOM format.
        /// </summary>
        /// <param name="collectionValue">The collection value to write.</param>
        /// <param name="propertyName">The name of the property being written.</param>
        /// <param name="isTopLevel">true if writing a top-level property payload; otherwise false.</param>
        /// <param name="isWritingTopLevelCollection">true if writing a top-level collection payload instead of an entry.</param>
        /// <param name="beforePropertyAction">Action which is called before the property is written, if it's going to be written.</param>
        /// <param name="propertyTypeReference">The type reference of the collection value (or null if no metadata is available).</param>
        /// <param name="isOpenPropertyType">true if this property is undeclared and the owning type is open.</param>
        private void WriteCollectionValueProperty(
            ODataCollectionValue collectionValue,
            string propertyName,
            bool isTopLevel,
            bool isWritingTopLevelCollection,
            Action beforePropertyAction,
            IEdmTypeReference propertyTypeReference,
            bool isOpenPropertyType)
        {
            ODataVersionChecker.CheckCollectionValueProperties(this.Version, propertyName);

            this.WritePropertyStart(beforePropertyAction, propertyName, isWritingTopLevelCollection, isTopLevel);
            this.WriteCollectionValue(collectionValue, propertyTypeReference, isOpenPropertyType, isWritingTopLevelCollection);
            this.WritePropertyEnd();
        }
Ejemplo n.º 10
0
 internal static string ConvertToUriCollectionLiteral(ODataCollectionValue collectionValue, IEdmModel model, ODataVersion version)
 {
     ExceptionUtils.CheckArgumentNotNull<ODataCollectionValue>(collectionValue, "collectionValue");
     ExceptionUtils.CheckArgumentNotNull<IEdmModel>(model, "model");
     ODataVersionChecker.CheckCollectionValue(version);
     StringBuilder sb = new StringBuilder();
     using (TextWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture))
     {
         JsonWriter jsonWriter = new JsonWriter(writer, false);
         ODataMessageWriterSettings messageWriterSettings = new ODataMessageWriterSettings {
             Version = new ODataVersion?(version)
         };
         using (ODataJsonOutputContext context = ODataJsonOutputContext.Create(ODataFormat.VerboseJson, jsonWriter, messageWriterSettings, false, model, null))
         {
             new ODataJsonPropertyAndValueSerializer(context).WriteCollectionValue(collectionValue, null, false);
         }
     }
     return sb.ToString();
 }
Ejemplo n.º 11
0
        /// <summary>
        /// Converts a primitive to a string for use in a Url.
        /// </summary>
        /// <param name="value">Value to convert.</param>
        /// <param name="version">OData version to be compliant with.</param>
        /// <returns>A string representation of <paramref name="value"/> to be added to a Url.</returns>
        internal static string ConvertToUriPrimitiveLiteral(object value, ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(value, "value");

            /* This should have the same behavior of Astoria with these differences: (iawillia, 10/7/11)
             * TODO BUG 292670: Differences between Astoria and ODL's Uri literals
             * 1) Cannot handle the System.Data.Linq.Binary type
             * 2) Cannot handle the System.Data.Linq.XElement type
             * 3) Astoria does not put a 'd' or 'D' on double values
             */

            if (value is ISpatial)
            {
                ODataVersionChecker.CheckSpatialValue(version);
            }

            // for legacy backwards compatibility reasons, use the formatter which does not URL-encode the resulting string.
            return(LiteralFormatter.ForConstantsWithoutEncoding.Format(value));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Converts the given <paramref name="value"/> to a corresponding CLR type. Expects the
        /// <paramref name="value"/> to have already been properly unescaped from an actual Uri.
        /// </summary>
        /// <param name="value">Value from a Uri to be converted.</param>
        /// <param name="version">Version to be compliant with.</param>
        /// <param name="model">Optional model to perform verification against.</param>
        /// <param name="typeReference">Optional IEdmTypeReference to perform verification against.
        ///  Callers must provide a <paramref name="model"/> containing this type if it is specified.</param>
        /// <returns>A CLR object that the <paramref name="value"/> represents.</returns>
        public static object ConvertFromUriLiteral(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
        {
            ExceptionUtils.CheckArgumentNotNull(value, "value");
            if (typeReference != null && model == null)
            {
                throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralTypeRefWithoutModel);
            }

            if (model == null)
            {
                model = Microsoft.Data.Edm.Library.EdmCoreModel.Instance;
            }

            // Let ExpressionLexer try to get a primitive
            ExpressionLexer lexer = new ExpressionLexer(value, false /*moveToFirstToken*/, false /*useSemicolonDelimeter*/);
            Exception       error;
            ExpressionToken token;

            lexer.TryPeekNextToken(out token, out error);

            if (token.Kind == ExpressionTokenKind.BracketedExpression)
            {
                // Should be a complex or collection value
                return(ODataUriConversionUtils.ConvertFromComplexOrCollectionValue(value, version, model, typeReference));
            }

            object result = lexer.ReadLiteralToken();

            // If we have a typeReference then perform verification and convert if necessary
            if (typeReference != null)
            {
                result = ODataUriConversionUtils.VerifyAndCoerceUriPrimitiveLiteral(result, model, typeReference, version);
            }

            if (result is ISpatial)
            {
                ODataVersionChecker.CheckSpatialValue(version);
            }

            return(result);
        }
Ejemplo n.º 13
0
 internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version)
 {
     ExceptionUtils.CheckArgumentNotNull<object>(primitiveValue, "primitiveValue");
     ExceptionUtils.CheckArgumentNotNull<IEdmModel>(model, "model");
     ExceptionUtils.CheckArgumentNotNull<IEdmTypeReference>(expectedTypeReference, "expectedTypeReference");
     ODataUriNullValue value2 = primitiveValue as ODataUriNullValue;
     if (value2 != null)
     {
         if (!expectedTypeReference.IsNullable)
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName()));
         }
         IEdmType type = ValidationUtils.ValidateValueTypeName(model, value2.TypeName, expectedTypeReference.Definition.TypeKind);
         if (type.IsSpatial())
         {
             ODataVersionChecker.CheckSpatialValue(version);
         }
         if (!TypePromotionUtils.CanConvertTo(type.ToTypeReference(), expectedTypeReference))
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), value2.TypeName));
         }
         value2.TypeName = expectedTypeReference.ODataFullName();
         return value2;
     }
     IEdmPrimitiveTypeReference reference = expectedTypeReference.AsPrimitiveOrNull();
     if (reference == null)
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue));
     }
     object obj2 = CoerceNumericType(primitiveValue, reference.PrimitiveDefinition());
     if (obj2 != null)
     {
         return obj2;
     }
     Type c = primitiveValue.GetType();
     if (!TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(reference)).IsAssignableFrom(c))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(reference.ODataFullName(), primitiveValue));
     }
     return primitiveValue;
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Converts a <see cref="ODataCollectionValue"/> to a string for use in a Url.
        /// </summary>
        /// <param name="collectionValue">Instance to convert.</param>
        /// <param name="model">Model to be used for validation. User model is optional. The EdmLib core model is expected as a minimum.</param>
        /// <param name="version">Version to be compliant with. Collection requires >= V3.</param>
        /// <returns>A string representation of <paramref name="collectionValue"/> to be added to a Url.</returns>
        internal static string ConvertToUriCollectionLiteral(ODataCollectionValue collectionValue, IEdmModel model, ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(collectionValue, "collectionValue");
            ExceptionUtils.CheckArgumentNotNull(model, "model");

            ODataVersionChecker.CheckCollectionValue(version);

            StringBuilder builder = new StringBuilder();

            using (TextWriter textWriter = new StringWriter(builder, CultureInfo.InvariantCulture))
            {
                JsonWriter jsonWriter = new JsonWriter(textWriter, false);
                ODataMessageWriterSettings messageWriterSettings = new ODataMessageWriterSettings()
                {
                    Version = version
                };

                // Calling dispose since it's the right thing to do, but when created from JsonWriter
                // the output context Dispose will not actually dispose anything, it will just cleanup itself.
                using (ODataJsonOutputContext jsonOutputContext = ODataJsonOutputContext.Create(
                           ODataFormat.VerboseJson,
                           jsonWriter,
                           messageWriterSettings,
                           false /*writingResponse*/,
                           model,
                           null /*urlResolver*/))
                {
                    ODataJsonPropertyAndValueSerializer jsonPropertyAndValueSerializer = new ODataJsonPropertyAndValueSerializer(jsonOutputContext);

                    jsonPropertyAndValueSerializer.WriteCollectionValue(
                        collectionValue,
                        null, /*propertyTypeRefereence*/
                        false /*openPropertyType - this determines if the TypeName will be written*/);
                    jsonPropertyAndValueSerializer.AssertRecursionDepthIsZero();
                }
            }

            return(builder.ToString());
        }
        /// <summary>
        /// Writes a name/value pair for a property.
        /// </summary>
        /// <param name="property">The property to write out.</param>
        /// <param name="owningType">The type owning the property (or null if no metadata is available).</param>
        /// <param name="allowStreamProperty">Should pass in true if we are writing a property of an ODataEntry instance, false otherwise.
        /// Named stream properties should only be defined on ODataEntry instances.</param>
        /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param>
        /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param>
        private void WriteProperty(
            ODataProperty property,
            IEdmStructuredType owningType,
            bool allowStreamProperty,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();

            WriterValidationUtils.ValidatePropertyNotNull(property);
            if (projectedProperties.ShouldSkipProperty(property.Name))
            {
                return;
            }

            WriterValidationUtils.ValidateProperty(property);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
            IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(property.Name, owningType);

            // If the property is of Geography or Geometry type or the value is of Geography or Geometry type
            // make sure to check that the version is 3.0 or above.
            if ((edmProperty != null && edmProperty.Type.IsSpatial()) ||
                (edmProperty == null && property.Value is System.Spatial.ISpatial))
            {
                ODataVersionChecker.CheckSpatialValue(this.Version);
            }

            this.JsonWriter.WriteName(property.Name);
            object value = property.Value;

            if (value == null)
            {
                WriterValidationUtils.ValidateNullPropertyValue(edmProperty, this.MessageWriterSettings.WriterBehavior, this.Model);
                this.JsonWriter.WriteValue(null);
            }
            else
            {
                bool isOpenPropertyType = owningType != null && owningType.IsOpen && edmProperty == null;
                if (isOpenPropertyType)
                {
                    ValidationUtils.ValidateOpenPropertyValue(property.Name, value);
                }

                IEdmTypeReference propertyTypeReference = edmProperty == null ? null : edmProperty.Type;
                ODataComplexValue complexValue          = value as ODataComplexValue;
                if (complexValue != null)
                {
                    this.WriteComplexValue(
                        complexValue,
                        propertyTypeReference,
                        isOpenPropertyType,
                        this.CreateDuplicatePropertyNamesChecker(),
                        /*collectionValidator*/ null);
                }
                else
                {
                    ODataCollectionValue collectionValue = value as ODataCollectionValue;
                    if (collectionValue != null)
                    {
                        ODataVersionChecker.CheckCollectionValueProperties(this.Version, property.Name);
                        this.WriteCollectionValue(
                            collectionValue,
                            propertyTypeReference,
                            isOpenPropertyType);
                    }
                    else
                    {
                        ODataStreamReferenceValue streamReferenceValue = value as ODataStreamReferenceValue;
                        if (streamReferenceValue != null)
                        {
                            if (!allowStreamProperty)
                            {
                                throw new ODataException(o.Strings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(property.Name));
                            }

                            Debug.Assert(owningType == null || owningType.IsODataEntityTypeKind(), "The metadata should not allow named stream properties to be defined on a non-entity type.");
                            WriterValidationUtils.ValidateStreamReferenceProperty(property, edmProperty, this.Version, this.WritingResponse);
                            this.WriteStreamReferenceValue((ODataStreamReferenceValue)property.Value);
                        }
                        else
                        {
                            this.WritePrimitiveValue(value, /*collectionValidator*/ null, propertyTypeReference);
                        }
                    }
                }
            }
        }
Ejemplo n.º 16
0
        protected override void EndEntry(ODataEntry entry)
        {
            Debug.Assert(
                this.ParentNavigationLink == null || !this.ParentNavigationLink.IsCollection.Value,
                "We should have already verified that the IsCollection matches the actual content of the link (feed/entry).");

            if (entry == null)
            {
                Debug.Assert(this.ParentNavigationLink != null, "When entry == null, it has to be an expanded single entry navigation.");

                // this is a null expanded single entry and it is null, an empty <m:inline /> will be written.
                this.CheckAndWriteParentNavigationLinkEndForInlineElement();
                return;
            }

            IEdmEntityType entryType = this.EntryEntityType;

            // Initialize the property value cache and cache the entry properties.
            EntryPropertiesValueCache propertyValueCache = new EntryPropertiesValueCache(entry);

            // NOTE: when writing, we assume the model has been validated already and thus pass int.MaxValue for the maxMappingCount.
            ODataEntityPropertyMappingCache epmCache = this.atomOutputContext.Model.EnsureEpmCache(entryType, /*maxMappingCount*/ int.MaxValue);

            // Populate the property value cache based on the EPM source tree information.
            // We do this since we need to write custom EPM after the properties below and don't
            // want to cache all properties just for the case that they are used in a custom EPM.
            if (epmCache != null)
            {
                EpmWriterUtils.CacheEpmProperties(propertyValueCache, epmCache.EpmSourceTree);
            }

            // Get the projected properties annotation
            ProjectedPropertiesAnnotation projectedProperties = entry.GetAnnotation <ProjectedPropertiesAnnotation>();

            AtomEntryScope    currentEntryScope = this.CurrentEntryScope;
            AtomEntryMetadata entryMetadata     = entry.Atom();

            if (!currentEntryScope.IsElementWritten(AtomElement.Id))
            {
                // NOTE: We write even null id, in that case we generate an empty atom:id element.
                this.atomEntryAndFeedSerializer.WriteEntryId(entry.Id);
            }

            Uri editLink = entry.EditLink;

            if (editLink != null && !currentEntryScope.IsElementWritten(AtomElement.EditLink))
            {
                this.atomEntryAndFeedSerializer.WriteEntryEditLink(editLink, entryMetadata);
            }

            Uri readLink = entry.ReadLink;

            if (readLink != null && !currentEntryScope.IsElementWritten(AtomElement.ReadLink))
            {
                this.atomEntryAndFeedSerializer.WriteEntryReadLink(readLink, entryMetadata);
            }

            // write entry metadata including syndication EPM
            AtomEntryMetadata epmEntryMetadata = null;

            if (epmCache != null)
            {
                ODataVersionChecker.CheckEntityPropertyMapping(this.atomOutputContext.Version, entryType, this.atomOutputContext.Model);

                epmEntryMetadata = EpmSyndicationWriter.WriteEntryEpm(
                    epmCache.EpmTargetTree,
                    propertyValueCache,
                    entryType.ToTypeReference().AsEntity(),
                    this.atomOutputContext);
            }

            this.atomEntryAndFeedSerializer.WriteEntryMetadata(entryMetadata, epmEntryMetadata, this.updatedTime);

            // stream properties
            IEnumerable <ODataProperty> streamProperties = propertyValueCache.EntryStreamProperties;

            if (streamProperties != null)
            {
                foreach (ODataProperty streamProperty in streamProperties)
                {
                    this.atomEntryAndFeedSerializer.WriteStreamProperty(
                        streamProperty,
                        entryType,
                        this.DuplicatePropertyNamesChecker,
                        projectedProperties);
                }
            }

            // association links
            IEnumerable <ODataAssociationLink> associationLinks = entry.AssociationLinks;

            if (associationLinks != null)
            {
                foreach (ODataAssociationLink associationLink in associationLinks)
                {
                    this.atomEntryAndFeedSerializer.WriteAssociationLink(
                        associationLink,
                        entryType,
                        this.DuplicatePropertyNamesChecker,
                        projectedProperties);
                }
            }

            // actions
            IEnumerable <ODataAction> actions = entry.Actions;

            if (actions != null)
            {
                foreach (ODataAction action in actions)
                {
                    ValidationUtils.ValidateOperationNotNull(action, true);
                    this.atomEntryAndFeedSerializer.WriteOperation(action);
                }
            }

            // functions
            IEnumerable <ODataFunction> functions = entry.Functions;

            if (functions != null)
            {
                foreach (ODataFunction function in functions)
                {
                    ValidationUtils.ValidateOperationNotNull(function, false);
                    this.atomEntryAndFeedSerializer.WriteOperation(function);
                }
            }

            // write the content
            this.WriteEntryContent(
                entry,
                entryType,
                propertyValueCache,
                epmCache == null ? null : epmCache.EpmSourceTree.Root,
                projectedProperties);

            // write custom EPM
            if (epmCache != null)
            {
                EpmCustomWriter.WriteEntryEpm(
                    this.atomOutputContext.XmlWriter,
                    epmCache.EpmTargetTree,
                    propertyValueCache,
                    entryType.ToTypeReference().AsEntity(),
                    this.atomOutputContext);
            }

            // </entry>
            this.atomOutputContext.XmlWriter.WriteEndElement();

            this.EndEntryXmlCustomization(entry);

            this.CheckAndWriteParentNavigationLinkEndForInlineElement();
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Writes a single property in ATOM format.
        /// </summary>
        /// <param name="writer">The <see cref="XmlWriter"/> to write to.</param>
        /// <param name="metadata">The metadata provider to use or null if no metadata is available.</param>
        /// <param name="property">The property to write out.</param>
        /// <param name="owningType">The type owning the property (or null if no metadata is available).</param>
        /// <param name="version">The protocol version used for writing.</param>
        /// <param name="isTopLevel">True if writing a top-level property payload; otherwise false.</param>
        /// <param name="isWritingCollection">True if we are writing a collection instead of an entry.</param>
        /// <param name="epmValueCache">Cache of values used in EPM so that we avoid multiple enumerations of properties/items. (can be null)</param>
        /// <param name="epmParentSourcePathSegment">The EPM source path segment which points to the property which sub-property we're writing. (can be null)</param>
        internal static void WriteProperty(
            XmlWriter writer,
            DataServiceMetadataProviderWrapper metadata,
            ODataProperty property,
            ResourceType owningType,
            ODataVersion version,
            bool isTopLevel,
            bool isWritingCollection,
            EpmValueCache epmValueCache,
            EpmSourcePathSegment epmParentSourcePathSegment)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");

            ValidationUtils.ValidateProperty(property);
            ResourceProperty resourceProperty = ValidationUtils.ValidatePropertyDefined(property.Name, owningType);

            EpmSourcePathSegment epmSourcePathSegment = null;

            if (epmParentSourcePathSegment != null)
            {
                epmSourcePathSegment = epmParentSourcePathSegment.SubProperties.Where(subProperty => subProperty.PropertyName == property.Name).FirstOrDefault();
            }

            object value = property.Value;

            // TODO: If we implement validation or type conversions the value needs to be converted here
            //       since the next method call needs to know if the value is a string or not in some cases.

            // If EPM tells us to skip this property in content, then we're done here.
            if (!ShouldWritePropertyInContent(value, epmSourcePathSegment, version))
            {
                return;
            }

            // <d:propertyname>
            writer.WriteStartElement(
                isWritingCollection ? string.Empty : AtomConstants.ODataNamespacePrefix,
                property.Name,
                AtomConstants.ODataNamespace);

            if (isTopLevel)
            {
                WriteDefaultNamespaceAttributes(writer, DefaultNamespaceFlags.OData | DefaultNamespaceFlags.ODataMetadata);
            }

            // Null property value.
            if (value == null)
            {
                // verify that MultiValue properties are not null
                if (resourceProperty != null && resourceProperty.Kind == ResourcePropertyKind.MultiValue)
                {
                    throw new ODataException(Strings.ODataWriter_MultiValuePropertiesMustNotHaveNullValue(resourceProperty.Name));
                }

                ODataAtomWriterUtils.WriteNullAttribute(writer);
            }
            else
            {
                ODataComplexValue complexValue         = value as ODataComplexValue;
                ResourceType      resourcePropertyType = resourceProperty == null ? null : resourceProperty.ResourceType;
                bool isOpenPropertyType = owningType != null && owningType.IsOpenType && resourceProperty == null;

                // Complex properties are written recursively.
                if (complexValue != null)
                {
                    WriteComplexValue(writer, metadata, complexValue, resourcePropertyType, isOpenPropertyType, isWritingCollection, version, epmValueCache, epmSourcePathSegment);
                }
                else
                {
                    ODataMultiValue multiValue = value as ODataMultiValue;
                    if (multiValue != null)
                    {
                        ODataVersionChecker.CheckMultiValueProperties(version, property.Name);
                        WriteMultiValue(writer, metadata, multiValue, resourcePropertyType, isOpenPropertyType, isWritingCollection, version, epmValueCache, epmSourcePathSegment);
                    }
                    else
                    {
                        WritePrimitiveValue(writer, value, resourcePropertyType);
                    }
                }
            }

            // </d:propertyname>
            writer.WriteEndElement();
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Writes a single property in ATOM format.
        /// </summary>
        /// <param name="property">The property to write out.</param>
        /// <param name="owningType">The owning type for the <paramref name="property"/> or null if no metadata is available.</param>
        /// <param name="isTopLevel">true if writing a top-level property payload; otherwise false.</param>
        /// <param name="isWritingCollection">true if we are writing a top-level collection instead of an entry.</param>
        /// <param name="beforePropertyAction">Action which is called before the property is written, if it's going to be written.</param>
        /// <param name="epmValueCache">Cache of values used in EPM so that we avoid multiple enumerations of properties/items. (can be null)</param>
        /// <param name="epmParentSourcePathSegment">The EPM source path segment which points to the property which sub-property we're writing. (can be null)</param>
        /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param>
        /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param>
        /// <returns>true if the property was actually written, false otherwise.</returns>
        private bool WriteProperty(
            ODataProperty property,
            IEdmStructuredType owningType,
            bool isTopLevel,
            bool isWritingCollection,
            Action beforePropertyAction,
            EpmValueCache epmValueCache,
            EpmSourcePathSegment epmParentSourcePathSegment,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();

            WriterValidationUtils.ValidatePropertyNotNull(property);

            object value        = property.Value;
            string propertyName = property.Name;
            EpmSourcePathSegment epmSourcePathSegment = EpmWriterUtils.GetPropertySourcePathSegment(epmParentSourcePathSegment, propertyName);

            //// TODO: If we implement type conversions the value needs to be converted here
            ////       since the next method call needs to know if the value is a string or not in some cases.

            ODataComplexValue             complexValue = value as ODataComplexValue;
            ProjectedPropertiesAnnotation complexValueProjectedProperties = null;

            if (!this.ShouldWritePropertyInContent(owningType, projectedProperties, propertyName, value, epmSourcePathSegment))
            {
                // If ShouldWritePropertyInContent returns false for a comlex value we have to continue
                // writing the property but set the projectedProperties to an empty array. The reason for this
                // is that we might find EPM on a nested property that has a null value and thus must be written
                // in content (in which case the parent property also has to be written).
                // This only applies if we have EPM information for the property.
                if (epmSourcePathSegment != null && complexValue != null)
                {
                    Debug.Assert(!projectedProperties.IsPropertyProjected(propertyName), "ShouldWritePropertyInContent must not return false for a projected complex property.");
                    complexValueProjectedProperties = ProjectedPropertiesAnnotation.EmptyProjectedPropertiesInstance;
                }
                else
                {
                    return(false);
                }
            }

            WriterValidationUtils.ValidatePropertyName(propertyName);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
            IEdmProperty      edmProperty           = WriterValidationUtils.ValidatePropertyDefined(propertyName, owningType, this.MessageWriterSettings.UndeclaredPropertyBehaviorKinds);
            IEdmTypeReference propertyTypeReference = edmProperty == null ? null : edmProperty.Type;

            if (value is ODataStreamReferenceValue)
            {
                throw new ODataException(ODataErrorStrings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
            }

            // If the property is of Geography or Geometry type or the value is of Geography or Geometry type
            // make sure to check that the version is 3.0 or above.
            if ((propertyTypeReference != null && propertyTypeReference.IsSpatial()) ||
                (propertyTypeReference == null && value is System.Spatial.ISpatial))
            {
                ODataVersionChecker.CheckSpatialValue(this.Version);
            }

            // Null property value.
            if (value == null)
            {
                this.WriteNullPropertyValue(propertyTypeReference, propertyName, isTopLevel, isWritingCollection, beforePropertyAction);
                return(true);
            }

            bool isOpenPropertyType = owningType != null && owningType.IsOpen && propertyTypeReference == null;

            if (isOpenPropertyType)
            {
                ValidationUtils.ValidateOpenPropertyValue(propertyName, value, this.MessageWriterSettings.UndeclaredPropertyBehaviorKinds);
            }

            if (complexValue != null)
            {
                return(this.WriteComplexValueProperty(
                           complexValue,
                           propertyName,
                           isTopLevel,
                           isWritingCollection,
                           beforePropertyAction,
                           epmValueCache,
                           propertyTypeReference,
                           isOpenPropertyType,
                           epmSourcePathSegment,
                           complexValueProjectedProperties));
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                this.WriteCollectionValueProperty(
                    collectionValue,
                    propertyName,
                    isTopLevel,
                    isWritingCollection,
                    beforePropertyAction,
                    propertyTypeReference,
                    isOpenPropertyType);

                return(true);
            }

            // If the value isn't one of the value types tested for already, it must be a non-null primitive.
            this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
            SerializationTypeNameAnnotation serializationTypeNameAnnotation = property.ODataValue.GetAnnotation <SerializationTypeNameAnnotation>();

            this.WritePrimitiveValue(value, /*collectionValidator*/ null, propertyTypeReference, serializationTypeNameAnnotation);
            this.WritePropertyEnd();
            return(true);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Writes the syndication part of EPM for an entry into ATOM metadata OM.
        /// </summary>
        /// <param name="epmTargetTree">The EPM target tree to use.</param>
        /// <param name="epmValueCache">The entry properties value cache to use to access the properties.</param>
        /// <param name="resourceType">The resource type of the entry.</param>
        /// <param name="metadata">The metadata provider to use.</param>
        /// <param name="version">The version of OData protocol to use.</param>
        /// <returns>The ATOM metadata OM with the EPM values populated.</returns>
        internal static AtomEntryMetadata WriteEntryEpm(
            EpmTargetTree epmTargetTree,
            EntryPropertiesValueCache epmValueCache,
            ResourceType resourceType,
            DataServiceMetadataProviderWrapper metadata,
            ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(epmTargetTree != null, "epmTargetTree != null");
            Debug.Assert(epmValueCache != null, "epmValueCache != null");
            Debug.Assert(resourceType != null, "For any EPM to exist the metadata must be available.");

            // If there are no syndication mappings, just return null.
            EpmTargetPathSegment syndicationRootSegment = epmTargetTree.SyndicationRoot;

            Debug.Assert(syndicationRootSegment != null, "EPM Target tree must always have syndication root.");
            if (syndicationRootSegment.SubSegments.Count == 0)
            {
                return(null);
            }

            AtomEntryMetadata entryMetadata = new AtomEntryMetadata();

            foreach (EpmTargetPathSegment targetSegment in syndicationRootSegment.SubSegments)
            {
                if (targetSegment.IsMultiValueProperty)
                {
                    Debug.Assert(
                        targetSegment.EpmInfo != null && targetSegment.EpmInfo.Attribute != null,
                        "MultiValue property target segment must have EpmInfo and the Epm Attribute.");

                    ODataVersionChecker.CheckMultiValueProperties(version, targetSegment.EpmInfo.Attribute.SourcePath);

                    // WriteMultiValueEpm(entry, targetSegment, epmValueCache);
                    throw new NotImplementedException();
                }
                else if (targetSegment.HasContent)
                {
                    EntityPropertyMappingInfo epmInfo = targetSegment.EpmInfo;
                    Debug.Assert(
                        epmInfo != null && epmInfo.Attribute != null,
                        "If the segment has content it must have EpmInfo which in turn must have the Epm attribute");

                    bool   nullOnParentProperty;
                    object propertyValue     = epmInfo.ReadEntryPropertyValue(epmValueCache, resourceType, metadata, out nullOnParentProperty);
                    string textPropertyValue = EpmWriterUtils.GetPropertyValueAsText(propertyValue);

                    switch (epmInfo.Attribute.TargetSyndicationItem)
                    {
                    case SyndicationItemProperty.Updated:
                        entryMetadata.Updated = CreateDateTimeValue(propertyValue, SyndicationItemProperty.Updated, version);
                        break;

                    case SyndicationItemProperty.Published:
                        entryMetadata.Published = CreateDateTimeValue(propertyValue, SyndicationItemProperty.Published, version);
                        break;

                    case SyndicationItemProperty.Rights:
                        entryMetadata.Rights = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                        break;

                    case SyndicationItemProperty.Summary:
                        entryMetadata.Summary = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                        break;

                    case SyndicationItemProperty.Title:
                        entryMetadata.Title = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                        break;

                    default:
                        throw new ODataException(Strings.General_InternalError(InternalErrorCodes.EpmSyndicationWriter_WriteEntryEpm_ContentTarget));
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomAuthorElementName)
                {
                    AtomPersonMetadata authorMetadata = WritePersonEpm(targetSegment, epmValueCache, resourceType, metadata);

                    Debug.Assert(entryMetadata.Authors == null, "Found two mappings to author, that is invalid.");
                    if (authorMetadata != null)
                    {
                        entryMetadata.Authors = CreateSinglePersonList(authorMetadata);
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomContributorElementName)
                {
                    AtomPersonMetadata contributorMetadata = WritePersonEpm(targetSegment, epmValueCache, resourceType, metadata);

                    Debug.Assert(entryMetadata.Contributors == null, "Found two mappings to contributor, that is invalid.");
                    if (contributorMetadata != null)
                    {
                        entryMetadata.Contributors = CreateSinglePersonList(contributorMetadata);
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomLinkElementName)
                {
                    AtomLinkMetadata linkMetadata = new AtomLinkMetadata();
                    //// WriteLinkEpm(entry, targetSegment, epmValueCache);

                    Debug.Assert(targetSegment.CriteriaValue != null, "Mapping to link must be conditional.");
                    linkMetadata.Relation = targetSegment.CriteriaValue;
                    List <AtomLinkMetadata> links;
                    if (entryMetadata.Links == null)
                    {
                        links = new List <AtomLinkMetadata>();
                        entryMetadata.Links = links;
                    }
                    else
                    {
                        links = entryMetadata.Links as List <AtomLinkMetadata>;
                        Debug.Assert(links != null, "AtomEntryMetadata.Links must be of type List<AtomLinkMetadata> since we create it like that.");
                    }

                    links.Add(linkMetadata);

                    throw new NotImplementedException();
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomCategoryElementName)
                {
                    AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata();
                    //// WriteCategoryEpm(entry, targetSegment, epmValueCache)

                    Debug.Assert(targetSegment.CriteriaValue != null, "Mapping to category must be conditional.");
                    categoryMetadata.Scheme = targetSegment.CriteriaValue;
                    List <AtomCategoryMetadata> categories;
                    if (entryMetadata.Categories == null)
                    {
                        categories = new List <AtomCategoryMetadata>();
                        entryMetadata.Categories = categories;
                    }
                    else
                    {
                        categories = entryMetadata.Links as List <AtomCategoryMetadata>;
                        Debug.Assert(categories != null, "AtomEntryMetadata.Categories must be of type List<AtomCategoryMetadata> since we create it like that.");
                    }

                    categories.Add(categoryMetadata);

                    throw new NotImplementedException();
                }
                else
                {
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.EpmSyndicationWriter_WriteEntryEpm_TargetSegment));
                }
            }

            return(entryMetadata);
        }
Ejemplo n.º 20
0
 protected override void EndEntry(ODataEntry entry)
 {
     if (entry == null)
     {
         this.CheckAndWriteParentNavigationLinkEndForInlineElement();
     }
     else
     {
         IEdmEntityType                  entryEntityType    = base.EntryEntityType;
         EntryPropertiesValueCache       propertyValueCache = new EntryPropertiesValueCache(entry);
         ODataEntityPropertyMappingCache cache2             = this.atomOutputContext.Model.EnsureEpmCache(entryEntityType, 0x7fffffff);
         if (cache2 != null)
         {
             EpmWriterUtils.CacheEpmProperties(propertyValueCache, cache2.EpmSourceTree);
         }
         ProjectedPropertiesAnnotation projectedProperties = entry.GetAnnotation <ProjectedPropertiesAnnotation>();
         AtomEntryScope    currentEntryScope = this.CurrentEntryScope;
         AtomEntryMetadata entryMetadata     = entry.Atom();
         if (!currentEntryScope.IsElementWritten(AtomElement.Id))
         {
             this.atomEntryAndFeedSerializer.WriteEntryId(entry.Id);
         }
         Uri editLink = entry.EditLink;
         if ((editLink != null) && !currentEntryScope.IsElementWritten(AtomElement.EditLink))
         {
             this.atomEntryAndFeedSerializer.WriteEntryEditLink(editLink, entryMetadata);
         }
         Uri readLink = entry.ReadLink;
         if ((readLink != null) && !currentEntryScope.IsElementWritten(AtomElement.ReadLink))
         {
             this.atomEntryAndFeedSerializer.WriteEntryReadLink(readLink, entryMetadata);
         }
         AtomEntryMetadata epmEntryMetadata = null;
         if (cache2 != null)
         {
             ODataVersionChecker.CheckEntityPropertyMapping(this.atomOutputContext.Version, entryEntityType, this.atomOutputContext.Model);
             epmEntryMetadata = EpmSyndicationWriter.WriteEntryEpm(cache2.EpmTargetTree, propertyValueCache, entryEntityType.ToTypeReference().AsEntity(), this.atomOutputContext);
         }
         this.atomEntryAndFeedSerializer.WriteEntryMetadata(entryMetadata, epmEntryMetadata, this.updatedTime);
         IEnumerable <ODataProperty> entryStreamProperties = propertyValueCache.EntryStreamProperties;
         if (entryStreamProperties != null)
         {
             foreach (ODataProperty property in entryStreamProperties)
             {
                 this.atomEntryAndFeedSerializer.WriteStreamProperty(property, entryEntityType, base.DuplicatePropertyNamesChecker, projectedProperties);
             }
         }
         IEnumerable <ODataAssociationLink> associationLinks = entry.AssociationLinks;
         if (associationLinks != null)
         {
             foreach (ODataAssociationLink link in associationLinks)
             {
                 this.atomEntryAndFeedSerializer.WriteAssociationLink(link, entryEntityType, base.DuplicatePropertyNamesChecker, projectedProperties);
             }
         }
         IEnumerable <ODataAction> actions = entry.Actions;
         if (actions != null)
         {
             foreach (ODataAction action in actions)
             {
                 ValidationUtils.ValidateOperationNotNull(action, true);
                 this.atomEntryAndFeedSerializer.WriteOperation(action);
             }
         }
         IEnumerable <ODataFunction> functions = entry.Functions;
         if (functions != null)
         {
             foreach (ODataFunction function in functions)
             {
                 ValidationUtils.ValidateOperationNotNull(function, false);
                 this.atomEntryAndFeedSerializer.WriteOperation(function);
             }
         }
         this.WriteEntryContent(entry, entryEntityType, propertyValueCache, (cache2 == null) ? null : cache2.EpmSourceTree.Root, projectedProperties);
         if (cache2 != null)
         {
             EpmCustomWriter.WriteEntryEpm(this.atomOutputContext.XmlWriter, cache2.EpmTargetTree, propertyValueCache, entryEntityType.ToTypeReference().AsEntity(), this.atomOutputContext);
         }
         this.atomOutputContext.XmlWriter.WriteEndElement();
         this.EndEntryXmlCustomization(entry);
         this.CheckAndWriteParentNavigationLinkEndForInlineElement();
     }
 }
Ejemplo n.º 21
0
        /// <summary>
        /// Reads a collection value.
        /// </summary>
        /// <param name="collectionValueTypeReference">The collection type reference of the value.</param>
        /// <param name="payloadTypeName">The type name read from the payload.</param>
        /// <param name="serializationTypeNameAnnotation">The serialization type name for the collection value (possibly null).</param>
        /// <returns>The value of the collection.</returns>
        /// <remarks>
        /// Pre-Condition:  Fails if the current node is not a JsonNodeType.StartObject
        /// Post-Condition: almost anything - the node after the collection value (after the EndObject)
        /// </remarks>
        private ODataCollectionValue ReadCollectionValueImplementation(
            IEdmCollectionTypeReference collectionValueTypeReference,
            string payloadTypeName,
            SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(
                collectionValueTypeReference == null || collectionValueTypeReference.IsNonEntityCollectionType(),
                "If the metadata is specified it must denote a Collection for this method to work.");
            this.JsonReader.AssertNotBuffering();

            ODataVersionChecker.CheckCollectionValue(this.Version);

            this.IncreaseRecursionDepth();

            // Read over the start object
            this.JsonReader.ReadStartObject();

            ODataCollectionValue collectionValue = new ODataCollectionValue();

            collectionValue.TypeName = collectionValueTypeReference != null?collectionValueTypeReference.ODataFullName() : payloadTypeName;

            if (serializationTypeNameAnnotation != null)
            {
                collectionValue.SetAnnotation(serializationTypeNameAnnotation);
            }

            List <object> items = null;
            bool          metadataPropertyFound = false;

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                string propertyName = this.JsonReader.ReadPropertyName();

                if (string.CompareOrdinal(JsonConstants.ODataMetadataName, propertyName) == 0)
                {
                    // __metadata property
                    if (metadataPropertyFound)
                    {
                        throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper(JsonConstants.ODataMetadataName));
                    }

                    metadataPropertyFound = true;

                    // Note that we don't need to read the type name again, as we've already read it above in FindTypeNameInPayload.
                    // There's nothing else of interest in the __metadata for collections.
                    this.JsonReader.SkipValue();
                }
                else if (string.CompareOrdinal(JsonConstants.ODataResultsName, propertyName) == 0)
                {
                    // results property
                    if (items != null)
                    {
                        throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper(JsonConstants.ODataResultsName));
                    }

                    items = new List <object>();

                    this.JsonReader.ReadStartArray();

                    DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();
                    IEdmTypeReference             itemType = null;
                    if (collectionValueTypeReference != null)
                    {
                        itemType = collectionValueTypeReference.CollectionDefinition().ElementType;
                    }

                    // NOTE: we do not support reading Verbose JSON without metadata right now so we always have an expected item type;
                    //       The collection validator is always null.
                    CollectionWithoutExpectedTypeValidator collectionValidator = null;

                    while (this.JsonReader.NodeType != JsonNodeType.EndArray)
                    {
                        object itemValue = this.ReadNonEntityValueImplementation(
                            itemType,
                            duplicatePropertyNamesChecker,
                            collectionValidator,
                            /*validateNullValue*/ true,
                            /*propertyName*/ null);

                        // Validate the item (for example that it's not null)
                        ValidationUtils.ValidateCollectionItem(itemValue, false /* isStreamable */);

                        // Note that the ReadNonEntityValue already validated that the actual type of the value matches
                        // the expected type (the itemType).
                        items.Add(itemValue);
                    }

                    Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndArray, "The results value must end with an end array.");
                    this.JsonReader.ReadEndArray();
                }
                else
                {
                    // Skip over any other property in the collection object
                    this.JsonReader.SkipValue();
                }
            }

            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndObject, "After all properties of Collection wrapper are read the EndObject node is expected.");
            this.JsonReader.ReadEndObject();

            if (items == null)
            {
                // We didn't find any results property. All collections must have the results property.
                throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_CollectionWithoutResults);
            }

            collectionValue.Items = new ReadOnlyEnumerable(items);

            this.JsonReader.AssertNotBuffering();
            this.DecreaseRecursionDepth();

            return(collectionValue);
        }
        private void WriteProperty(
            ODataProperty property,
            IEdmStructuredType owningType,
            bool isTopLevel,
            bool allowStreamProperty,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();

            WriterValidationUtils.ValidatePropertyNotNull(property);

            string propertyName = property.Name;

            if (projectedProperties.ShouldSkipProperty(propertyName))
            {
                return;
            }

            WriterValidationUtils.ValidatePropertyName(propertyName);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
            IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(propertyName, owningType, this.MessageWriterSettings.UndeclaredPropertyBehaviorKinds);
            bool         shouldWriteRawAnnotations = false;

            if (!ShouldWriteProperty(owningType, property, edmProperty, out shouldWriteRawAnnotations))
            {
                return;
            }

            IEdmTypeReference propertyTypeReference = edmProperty == null ? null : edmProperty.Type;
            bool alreadyWroteODataType = false;

            if (shouldWriteRawAnnotations)
            {
                TryWriteRawAnnotations(property, out alreadyWroteODataType);
            }

            // handle ODataUntypedValue
            ODataUntypedValue untypedValue = property.Value as ODataUntypedValue;

            if (untypedValue != null)
            {
                if (this.MessageWriterSettings.ContainUndeclaredPropertyBehavior(
                        ODataUndeclaredPropertyBehaviorKinds.SupportUndeclaredValueProperty))
                {
                    this.JsonWriter.WriteName(propertyName);
                    this.JsonWriter.WriteRawString(untypedValue.RawJson);
                }

                return;
            }

            ODataValue          value          = property.ODataValue;
            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            // If the property is of Geography or Geometry type or the value is of Geography or Geometry type
            // make sure to check that the version is 3.0 or above.
            bool isSpatial = (propertyTypeReference != null && propertyTypeReference.IsSpatial()) || (propertyTypeReference == null && primitiveValue != null && primitiveValue.Value is ISpatial);

            if (isSpatial)
            {
                ODataVersionChecker.CheckSpatialValue(this.Version);
            }

            ODataStreamReferenceValue streamReferenceValue = value as ODataStreamReferenceValue;

            if (streamReferenceValue != null)
            {
                if (!allowStreamProperty)
                {
                    throw new ODataException(ODataErrorStrings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
                }

                Debug.Assert(owningType == null || owningType.IsODataEntityTypeKind(), "The metadata should not allow named stream properties to be defined on a non-entity type.");
                Debug.Assert(!isTopLevel, "Stream properties are not allowed at the top level.");
                WriterValidationUtils.ValidateStreamReferenceProperty(property, edmProperty, this.Version, this.WritingResponse);
                this.WriteStreamReferenceProperty(propertyName, streamReferenceValue);
                return;
            }

            string wirePropertyName = isTopLevel ? JsonLightConstants.ODataValuePropertyName : propertyName;

            if (value is ODataNullValue || value == null)
            {
                WriterValidationUtils.ValidateNullPropertyValue(propertyTypeReference, propertyName, this.MessageWriterSettings.WriterBehavior, this.Model);

                if (isTopLevel)
                {
                    // Write the special null marker for top-level null properties.
                    this.JsonWriter.WriteName(ODataAnnotationNames.ODataNull);
                    this.JsonWriter.WriteValue(true);
                }
                else
                {
                    this.JsonWriter.WriteName(wirePropertyName);
                    this.JsonLightValueSerializer.WriteNullValue();
                }

                return;
            }

            bool isOpenPropertyType = IsOpenPropertyType(property, owningType, edmProperty);

            if (isOpenPropertyType)
            {
                ValidationUtils.ValidateOpenPropertyValue(propertyName, value, this.MessageWriterSettings.UndeclaredPropertyBehaviorKinds);
            }

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                if (!isTopLevel)
                {
                    this.JsonWriter.WriteName(wirePropertyName);
                }

                this.JsonLightValueSerializer.WriteComplexValue(complexValue, propertyTypeReference, isTopLevel, isOpenPropertyType, this.CreateDuplicatePropertyNamesChecker());
                return;
            }

            IEdmTypeReference    typeFromValue   = TypeNameOracle.ResolveAndValidateTypeNameForValue(this.Model, propertyTypeReference, value, isOpenPropertyType);
            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                if (!alreadyWroteODataType)
                {
                    string collectionTypeNameToWrite = this.JsonLightOutputContext.TypeNameOracle.GetValueTypeNameForWriting(collectionValue, propertyTypeReference, typeFromValue, isOpenPropertyType);
                    this.WritePropertyTypeName(wirePropertyName, collectionTypeNameToWrite, isTopLevel);
                }

                this.JsonWriter.WriteName(wirePropertyName);
                ODataVersionChecker.CheckCollectionValueProperties(this.Version, propertyName);

                // passing false for 'isTopLevel' because the outer wrapping object has already been written.
                this.JsonLightValueSerializer.WriteCollectionValue(collectionValue, propertyTypeReference, isTopLevel, false /*isInUri*/, isOpenPropertyType);
                return;
            }

            Debug.Assert(primitiveValue != null, "primitiveValue != null");

            if (!alreadyWroteODataType)
            {
                string typeNameToWrite = this.JsonLightOutputContext.TypeNameOracle.GetValueTypeNameForWriting(primitiveValue, propertyTypeReference, typeFromValue, isOpenPropertyType);
                this.WritePropertyTypeName(wirePropertyName, typeNameToWrite, isTopLevel);
            }

            this.JsonWriter.WriteName(wirePropertyName);
            this.JsonLightValueSerializer.WritePrimitiveValue(primitiveValue.Value, propertyTypeReference);
        }
Ejemplo n.º 23
0
        internal static string ConvertToUriPrimitiveLiteral(object value, ODataVersion version)
        {
            ExceptionUtils.CheckArgumentNotNull<object>(value, "value");
            StringBuilder builder = new StringBuilder();
            Type nullableType = value.GetType();
            nullableType = Nullable.GetUnderlyingType(nullableType) ?? nullableType;
            switch (Microsoft.Data.OData.PlatformHelper.GetTypeCode(nullableType))
            {
                case TypeCode.Object:
                    if (!(nullableType == typeof(byte[])))
                    {
                        if (nullableType == typeof(Guid))
                        {
                            builder.Append("guid");
                            builder.Append("'");
                            builder.Append(value.ToString());
                            builder.Append("'");
                        }
                        else if (nullableType == typeof(DateTimeOffset))
                        {
                            builder.Append("datetimeoffset");
                            builder.Append("'");
                            builder.Append(XmlConvert.ToString((DateTimeOffset) value));
                            builder.Append("'");
                        }
                        else if (nullableType == typeof(TimeSpan))
                        {
                            builder.Append("time");
                            builder.Append("'");
                            builder.Append(XmlConvert.ToString((TimeSpan) value));
                            builder.Append("'");
                        }
                        else if (typeof(Geography).IsAssignableFrom(nullableType))
                        {
                            ODataVersionChecker.CheckSpatialValue(version);
                            builder.Append("geography");
                            builder.Append("'");
                            builder.Append(WellKnownTextSqlFormatter.Create(true).Write((Geography) value));
                            builder.Append("'");
                        }
                        else
                        {
                            if (!typeof(Geometry).IsAssignableFrom(nullableType))
                            {
                                throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertToUriLiteralUnsupportedType(nullableType.ToString()));
                            }
                            ODataVersionChecker.CheckSpatialValue(version);
                            builder.Append("geometry");
                            builder.Append("'");
                            builder.Append(WellKnownTextSqlFormatter.Create(true).Write((Geometry) value));
                            builder.Append("'");
                        }
                        break;
                    }
                    builder.Append(ConvertByteArrayToKeyString((byte[]) value));
                    break;

                case TypeCode.Boolean:
                    builder.Append(XmlConvert.ToString((bool) value));
                    return builder.ToString();

                case TypeCode.SByte:
                    builder.Append(XmlConvert.ToString((sbyte) value));
                    return builder.ToString();

                case TypeCode.Byte:
                    builder.Append(XmlConvert.ToString((byte) value));
                    return builder.ToString();

                case TypeCode.Int16:
                    builder.Append(XmlConvert.ToString((short) value));
                    return builder.ToString();

                case TypeCode.Int32:
                    builder.Append(XmlConvert.ToString((int) value));
                    return builder.ToString();

                case TypeCode.Int64:
                    builder.Append(XmlConvert.ToString((long) value));
                    builder.Append("L");
                    return builder.ToString();

                case TypeCode.Single:
                    builder.Append(XmlConvert.ToString((float) value));
                    builder.Append("f");
                    return builder.ToString();

                case TypeCode.Double:
                    builder.Append(AppendDecimalMarkerToDouble(XmlConvert.ToString((double) value)));
                    builder.Append("D");
                    return builder.ToString();

                case TypeCode.Decimal:
                    builder.Append(XmlConvert.ToString((decimal) value));
                    builder.Append("M");
                    return builder.ToString();

                case TypeCode.DateTime:
                    builder.Append("datetime");
                    builder.Append("'");
                    builder.Append(Microsoft.Data.OData.PlatformHelper.ConvertDateTimeToString((DateTime) value));
                    builder.Append("'");
                    return builder.ToString();

                case TypeCode.String:
                    builder.Append("'");
                    builder.Append(((string) value).Replace("'", "''"));
                    builder.Append("'");
                    return builder.ToString();

                default:
                    throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertToUriLiteralUnsupportedType(nullableType.ToString()));
            }
            return builder.ToString();
        }
Ejemplo n.º 24
0
        private ODataCollectionValue ReadCollectionValueImplementation(IEdmCollectionTypeReference collectionValueTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            ODataVersionChecker.CheckCollectionValue(base.Version);
            this.IncreaseRecursionDepth();
            base.JsonReader.ReadStartObject();
            ODataCollectionValue value2 = new ODataCollectionValue {
                TypeName = (collectionValueTypeReference != null) ? collectionValueTypeReference.ODataFullName() : payloadTypeName
            };

            if (serializationTypeNameAnnotation != null)
            {
                value2.SetAnnotation <SerializationTypeNameAnnotation>(serializationTypeNameAnnotation);
            }
            List <object> sourceEnumerable = null;
            bool          flag             = false;

            while (base.JsonReader.NodeType == JsonNodeType.Property)
            {
                string strB = base.JsonReader.ReadPropertyName();
                if (string.CompareOrdinal("__metadata", strB) == 0)
                {
                    if (flag)
                    {
                        throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper("__metadata"));
                    }
                    flag = true;
                    base.JsonReader.SkipValue();
                }
                else
                {
                    if (string.CompareOrdinal("results", strB) == 0)
                    {
                        if (sourceEnumerable != null)
                        {
                            throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper("results"));
                        }
                        sourceEnumerable = new List <object>();
                        base.JsonReader.ReadStartArray();
                        DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker();
                        IEdmTypeReference             expectedTypeReference         = null;
                        if (collectionValueTypeReference != null)
                        {
                            expectedTypeReference = collectionValueTypeReference.CollectionDefinition().ElementType;
                        }
                        CollectionWithoutExpectedTypeValidator collectionValidator = null;
                        while (base.JsonReader.NodeType != JsonNodeType.EndArray)
                        {
                            object item = this.ReadNonEntityValueImplementation(expectedTypeReference, duplicatePropertyNamesChecker, collectionValidator, true);
                            ValidationUtils.ValidateCollectionItem(item, false);
                            sourceEnumerable.Add(item);
                        }
                        base.JsonReader.ReadEndArray();
                        continue;
                    }
                    base.JsonReader.SkipValue();
                }
            }
            base.JsonReader.ReadEndObject();
            if (sourceEnumerable == null)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_CollectionWithoutResults);
            }
            value2.Items = new ReadOnlyEnumerable(sourceEnumerable);
            this.DecreaseRecursionDepth();
            return(value2);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Converts a primitive to a string for use in a Url.
        /// </summary>
        /// <param name="value">Value to convert.</param>
        /// <param name="version">OData version to be compliant with.</param>
        /// <returns>A string representation of <paramref name="value"/> to be added to a Url.</returns>
        internal static string ConvertToUriPrimitiveLiteral(object value, ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(value, "value");

            /* This should have the same behavior of Astoria with these differences: (iawillia, 10/7/11)
             * TODO BUG 292670: Differences betwen Astoria and ODL's Uri literals
             * 1) Cannot handle the System.Data.Linq.Binary type
             * 2) Cannot handle the System.Data.Linq.XElement type
             * 3) Astoria does not put a 'd' or 'D' on double values
             */

            StringBuilder builder = new StringBuilder();

            Type valueType = value.GetType();

            valueType = Nullable.GetUnderlyingType(valueType) ?? valueType;

            TypeCode code = o.PlatformHelper.GetTypeCode(valueType);

            switch (code)
            {
            case TypeCode.Boolean:
                builder.Append(XmlConvert.ToString((bool)value));
                return(builder.ToString());

            case TypeCode.Byte:
                builder.Append(XmlConvert.ToString((byte)value));
                return(builder.ToString());

            case TypeCode.DateTime:
                builder.Append(ExpressionConstants.LiteralPrefixDateTime);
                builder.Append(ExpressionConstants.LiteralSingleQuote);
                builder.Append(o.PlatformHelper.ConvertDateTimeToString((DateTime)value));
                builder.Append(ExpressionConstants.LiteralSingleQuote);
                return(builder.ToString());

            case TypeCode.Decimal:
                builder.Append(XmlConvert.ToString((Decimal)value));
                builder.Append(ExpressionConstants.LiteralSuffixDecimal);
                return(builder.ToString());

            case TypeCode.Double:
                builder.Append(AppendDecimalMarkerToDouble(XmlConvert.ToString((Double)value)));
                builder.Append(ExpressionConstants.LiteralSuffixDouble);
                return(builder.ToString());

            case TypeCode.Int16:
                builder.Append(XmlConvert.ToString((Int16)value));
                return(builder.ToString());

            case TypeCode.Int32:
                builder.Append(XmlConvert.ToString((Int32)value));
                return(builder.ToString());

            case TypeCode.Int64:
                builder.Append(XmlConvert.ToString((Int64)value));
                builder.Append(ExpressionConstants.LiteralSuffixInt64);
                return(builder.ToString());

            case TypeCode.Object:
                if (valueType == typeof(byte[]))
                {
                    builder.Append(ConvertByteArrayToKeyString((byte[])value));
                }
                else if (valueType == typeof(Guid))
                {
                    builder.Append(ExpressionConstants.LiteralPrefixGuid);
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                    builder.Append(value.ToString());
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                }
                else if (valueType == typeof(DateTimeOffset))
                {
                    builder.Append(ExpressionConstants.LiteralPrefixDateTimeOffset);
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                    builder.Append(XmlConvert.ToString((DateTimeOffset)value));
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                }
                else if (valueType == typeof(TimeSpan))
                {
                    builder.Append(ExpressionConstants.LiteralPrefixTime);
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                    builder.Append(XmlConvert.ToString((TimeSpan)value));
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                }
                else if (typeof(Geography).IsAssignableFrom(valueType))
                {
                    ODataVersionChecker.CheckSpatialValue(version);
                    builder.Append(ExpressionConstants.LiteralPrefixGeography);
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                    builder.Append(WellKnownTextSqlFormatter.Create(true).Write((Geography)value));
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                }
                else if (typeof(Geometry).IsAssignableFrom(valueType))
                {
                    ODataVersionChecker.CheckSpatialValue(version);
                    builder.Append(ExpressionConstants.LiteralPrefixGeometry);
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                    builder.Append(WellKnownTextSqlFormatter.Create(true).Write((Geometry)value));
                    builder.Append(ExpressionConstants.LiteralSingleQuote);
                }
                else
                {
                    throw new ODataException(o.Strings.ODataUriUtils_ConvertToUriLiteralUnsupportedType(valueType.ToString()));
                }

                return(builder.ToString());

            case TypeCode.SByte:
                builder.Append(XmlConvert.ToString((SByte)value));
                return(builder.ToString());

            case TypeCode.Single:
                builder.Append(XmlConvert.ToString((Single)value));
                builder.Append(ExpressionConstants.LiteralSuffixSingle);
                return(builder.ToString());

            case TypeCode.String:
                builder.Append(ExpressionConstants.LiteralSingleQuote);
                builder.Append(((String)value).Replace("'", "''"));
                builder.Append(ExpressionConstants.LiteralSingleQuote);
                return(builder.ToString());

            default:
                throw new ODataException(o.Strings.ODataUriUtils_ConvertToUriLiteralUnsupportedType(valueType.ToString()));
            }
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Finish writing an entry.
        /// </summary>
        /// <param name="entry">The entry to write.</param>
        protected override void EndEntry(ODataEntry entry)
        {
            Debug.Assert(entry != null, "entry != null");

            string       typeName  = entry.TypeName;
            ResourceType entryType = ValidationUtils.ValidateTypeName(this.MetadataProvider, typeName, ResourceTypeKind.EntityType, false);

            // Initialize the property value cache and cache the entry properties.
            EntryPropertiesValueCache propertyValueCache        = new EntryPropertiesValueCache(entry);
            EpmResourceTypeAnnotation epmResourceTypeAnnotation = null;

            if (entryType != null)
            {
                Debug.Assert(entryType.IsReadOnly, "The resource must be read-only to be applied to an entry.");
                entryType.EnsureEpmAvailability();
                epmResourceTypeAnnotation = entryType.Epm();
            }

            // <atom:id>idValue</atom:id>
            // NOTE: do not generate a relative Uri for the ID; it is independent of xml:base
            ODataAtomWriterUtils.WriteElementWithTextContent(
                this.writer,
                AtomConstants.AtomNamespacePrefix,
                AtomConstants.AtomIdElementName,
                AtomConstants.AtomNamespace,
                entry.Id);

            // <category term="type" scheme="odatascheme"/>
            // If no type information is provided, don't include the category element for type at all
            // NOTE: the validation of the type name happened at the beginning of this method.
            if (typeName != null)
            {
                ODataAtomWriterMetadataUtils.WriteCategory(this.writer, typeName, AtomConstants.ODataSchemeNamespace, null);
            }

            Uri editLink = entry.EditLink;

            if (editLink != null)
            {
                // <link rel="edit" title="Title" href="LinkHRef"/>
                ODataAtomWriterUtils.WriteReadOrEditLink(this.writer, this.BaseUri, editLink, AtomConstants.AtomEditRelationAttributeValue, typeName);
            }

            Uri readLink = entry.ReadLink;

            if (readLink != null)
            {
                // <link rel="self" title="Title" href="LinkHRef"/>
                ODataAtomWriterUtils.WriteReadOrEditLink(this.writer, this.BaseUri, readLink, AtomConstants.AtomSelfRelationAttributeValue, typeName);
            }

            // named streams
            IEnumerable <ODataMediaResource> namedStreams = entry.NamedStreams;

            if (namedStreams != null)
            {
                foreach (ODataMediaResource namedStream in namedStreams)
                {
                    ValidationUtils.ValidateNamedStream(namedStream, this.Version);

                    ODataAtomWriterUtils.WriteNamedStream(this.writer, this.BaseUri, namedStream);
                }
            }

            // association links
            IEnumerable <ODataAssociationLink> associationLinks = entry.AssociationLinks;

            if (associationLinks != null)
            {
                foreach (ODataAssociationLink associationLink in associationLinks)
                {
                    ValidationUtils.ValidateAssociationLink(associationLink, this.Version);

                    ODataAtomWriterUtils.WriteAssociationLink(this.writer, this.BaseUri, entry, associationLink);
                }
            }

            // write entry metadata including syndication EPM
            AtomEntryMetadata epmEntryMetadata = null;

            if (epmResourceTypeAnnotation != null)
            {
                ODataVersionChecker.CheckEntityPropertyMapping(this.Version, entryType);

                epmEntryMetadata = EpmSyndicationWriter.WriteEntryEpm(
                    epmResourceTypeAnnotation.EpmTargetTree,
                    propertyValueCache,
                    entryType,
                    this.MetadataProvider,
                    this.Version);
            }

            ODataAtomWriterMetadataUtils.WriteEntryMetadata(this.writer, this.BaseUri, entry, epmEntryMetadata);

            // write the content
            this.WriteEntryContent(entry, entryType, propertyValueCache, epmResourceTypeAnnotation == null ? null : epmResourceTypeAnnotation.EpmSourceTree.Root);

            // write custom EPM
            if (epmResourceTypeAnnotation != null)
            {
                EpmCustomWriter.WriteEntryEpm(
                    this.writer,
                    epmResourceTypeAnnotation.EpmTargetTree,
                    propertyValueCache,
                    entryType,
                    this.MetadataProvider);
            }

            // </entry>
            this.writer.WriteEndElement();
        }
Ejemplo n.º 27
0
        private bool WriteProperty(ODataProperty property, IEdmStructuredType owningType, bool isTopLevel, bool isWritingCollection, Action beforePropertyAction, EpmValueCache epmValueCache, EpmSourcePathSegment epmParentSourcePathSegment, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties)
        {
            Action beforeValueAction = null;
            Action afterValueAction  = null;

            WriterValidationUtils.ValidatePropertyNotNull(property);
            object propertyValue = property.Value;
            string propertyName  = property.Name;
            EpmSourcePathSegment          propertySourcePathSegment = EpmWriterUtils.GetPropertySourcePathSegment(epmParentSourcePathSegment, propertyName);
            ODataComplexValue             complexValue = propertyValue as ODataComplexValue;
            ProjectedPropertiesAnnotation emptyProjectedPropertiesMarker = null;

            if (!this.ShouldWritePropertyInContent(owningType, projectedProperties, propertyName, propertyValue, propertySourcePathSegment))
            {
                if ((propertySourcePathSegment == null) || (complexValue == null))
                {
                    return(false);
                }
                emptyProjectedPropertiesMarker = ProjectedPropertiesAnnotation.EmptyProjectedPropertiesMarker;
            }
            WriterValidationUtils.ValidateProperty(property);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
            IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(propertyName, owningType);

            if (propertyValue is ODataStreamReferenceValue)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
            }
            if (((edmProperty != null) && edmProperty.Type.IsSpatial()) || ((edmProperty == null) && (propertyValue is ISpatial)))
            {
                ODataVersionChecker.CheckSpatialValue(base.Version);
            }
            if (propertyValue == null)
            {
                this.WriteNullPropertyValue(edmProperty, propertyName, isTopLevel, isWritingCollection, beforePropertyAction);
                return(true);
            }
            bool isOpenPropertyType = ((owningType != null) && owningType.IsOpen) && (edmProperty == null);

            if (isOpenPropertyType)
            {
                ValidationUtils.ValidateOpenPropertyValue(propertyName, propertyValue);
            }
            IEdmTypeReference metadataTypeReference = (edmProperty == null) ? null : edmProperty.Type;

            if (complexValue != null)
            {
                DuplicatePropertyNamesChecker checker = base.CreateDuplicatePropertyNamesChecker();
                if (isTopLevel)
                {
                    this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
                    this.WriteComplexValue(complexValue, metadataTypeReference, isOpenPropertyType, isWritingCollection, null, null, checker, null, epmValueCache, propertySourcePathSegment, null);
                    this.WritePropertyEnd();
                    return(true);
                }
                if (beforeValueAction == null)
                {
                    beforeValueAction = delegate {
                        this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
                    };
                }
                if (afterValueAction == null)
                {
                    afterValueAction = delegate {
                        this.WritePropertyEnd();
                    };
                }
                return(this.WriteComplexValue(complexValue, metadataTypeReference, isOpenPropertyType, isWritingCollection, beforeValueAction, afterValueAction, checker, null, epmValueCache, propertySourcePathSegment, emptyProjectedPropertiesMarker));
            }
            ODataCollectionValue collectionValue = propertyValue as ODataCollectionValue;

            if (collectionValue != null)
            {
                ODataVersionChecker.CheckCollectionValueProperties(base.Version, propertyName);
                this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
                this.WriteCollectionValue(collectionValue, metadataTypeReference, isOpenPropertyType, isWritingCollection);
                this.WritePropertyEnd();
                return(true);
            }
            this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
            this.WritePrimitiveValue(propertyValue, null, metadataTypeReference);
            this.WritePropertyEnd();
            return(true);
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Writes a single property in ATOM format.
        /// </summary>
        /// <param name="property">The property to write out.</param>
        /// <param name="owningType">The type owning the property (or null if no metadata is available).</param>
        /// <param name="isTopLevel">true if writing a top-level property payload; otherwise false.</param>
        /// <param name="isWritingCollection">true if we are writing a collection instead of an entry.</param>
        /// <param name="beforePropertyAction">Action which is called before the property is written, if it's going to be written.</param>
        /// <param name="epmValueCache">Cache of values used in EPM so that we avoid multiple enumerations of properties/items. (can be null)</param>
        /// <param name="epmParentSourcePathSegment">The EPM source path segment which points to the property which sub-property we're writing. (can be null)</param>
        /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param>
        /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param>
        /// <returns>true if the property was actually written, false otherwise.</returns>
        private bool WriteProperty(
            ODataProperty property,
            IEdmStructuredType owningType,
            bool isTopLevel,
            bool isWritingCollection,
            Action beforePropertyAction,
            EpmValueCache epmValueCache,
            EpmSourcePathSegment epmParentSourcePathSegment,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();

            WriterValidationUtils.ValidatePropertyNotNull(property);

            object value        = property.Value;
            string propertyName = property.Name;
            EpmSourcePathSegment epmSourcePathSegment = EpmWriterUtils.GetPropertySourcePathSegment(epmParentSourcePathSegment, propertyName);

            //// TODO: If we implement type conversions the value needs to be converted here
            ////       since the next method call needs to know if the value is a string or not in some cases.

            ODataComplexValue             complexValue = value as ODataComplexValue;
            ProjectedPropertiesAnnotation complexValueProjectedProperties = null;

            if (!this.ShouldWritePropertyInContent(owningType, projectedProperties, propertyName, value, epmSourcePathSegment))
            {
                // If ShouldWritePropertyInContent returns false for a comlex value we have to continue
                // writing the property but set the projectedProperties to an empty array. The reason for this
                // is that we might find EPM on a nested property that has a null value and thus must be written
                // in content (in which case the parent property also has to be written).
                // This only applies if we have EPM information for the property.
                if (epmSourcePathSegment != null && complexValue != null)
                {
                    Debug.Assert(!projectedProperties.IsPropertyProjected(propertyName), "ShouldWritePropertyInContent must not return false for a projected complex property.");
                    complexValueProjectedProperties = ProjectedPropertiesAnnotation.EmptyProjectedPropertiesMarker;
                }
                else
                {
                    return(false);
                }
            }

            WriterValidationUtils.ValidateProperty(property);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
            IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(propertyName, owningType);

            if (value is ODataStreamReferenceValue)
            {
                throw new ODataException(o.Strings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
            }

            // If the property is of Geography or Geometry type or the value is of Geography or Geometry type
            // make sure to check that the version is 3.0 or above.
            if ((edmProperty != null && edmProperty.Type.IsSpatial()) ||
                (edmProperty == null && value is System.Spatial.ISpatial))
            {
                ODataVersionChecker.CheckSpatialValue(this.Version);
            }

            // Null property value.
            if (value == null)
            {
                this.WriteNullPropertyValue(edmProperty, propertyName, isTopLevel, isWritingCollection, beforePropertyAction);
                return(true);
            }

            bool isOpenPropertyType = owningType != null && owningType.IsOpen && edmProperty == null;

            if (isOpenPropertyType)
            {
                ValidationUtils.ValidateOpenPropertyValue(propertyName, value);
            }

            IEdmTypeReference propertyTypeReference = edmProperty == null ? null : edmProperty.Type;

            if (complexValue != null)
            {
                // Complex properties are written recursively.
                DuplicatePropertyNamesChecker complexValuePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();
                if (isTopLevel)
                {
                    // Top-level property must always write the property element
                    Debug.Assert(complexValueProjectedProperties == null, "complexValueProjectedProperties == null");
                    this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
                    this.AssertRecursionDepthIsZero();
                    this.WriteComplexValue(
                        complexValue,
                        propertyTypeReference,
                        isOpenPropertyType,
                        isWritingCollection,
                        null /* beforeValueAction */,
                        null /* afterValueAction */,
                        complexValuePropertyNamesChecker,
                        null /* collectionValidator */,
                        epmValueCache,
                        epmSourcePathSegment,
                        null /* projectedProperties */);
                    this.AssertRecursionDepthIsZero();
                    this.WritePropertyEnd();
                    return(true);
                }

                return(this.WriteComplexValue(
                           complexValue,
                           propertyTypeReference,
                           isOpenPropertyType,
                           isWritingCollection,
                           () => this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel),
                           () => this.WritePropertyEnd(),
                           complexValuePropertyNamesChecker,
                           null /* collectionValidator */,
                           epmValueCache,
                           epmSourcePathSegment,
                           complexValueProjectedProperties));
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                ODataVersionChecker.CheckCollectionValueProperties(this.Version, propertyName);

                this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
                this.WriteCollectionValue(
                    collectionValue,
                    propertyTypeReference,
                    isOpenPropertyType,
                    isWritingCollection);
                this.WritePropertyEnd();
                return(true);
            }

            this.WritePropertyStart(beforePropertyAction, propertyName, isWritingCollection, isTopLevel);
            this.WritePrimitiveValue(value, /*collectionValidator*/ null, propertyTypeReference);
            this.WritePropertyEnd();
            return(true);
        }