internal void WriteComplexValue(ODataComplexValue complexValue, IEdmTypeReference propertyTypeReference, bool isOpenPropertyType, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator)
        {
            this.IncreaseRecursionDepth();
            base.JsonWriter.StartObjectScope();
            string typeName = complexValue.TypeName;

            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(typeName, EdmTypeKind.Complex);
            }
            IEdmComplexTypeReference type = WriterValidationUtils.ResolveTypeNameForWriting(base.Model, propertyTypeReference, ref typeName, EdmTypeKind.Complex, isOpenPropertyType).AsComplexOrNull();

            if (((typeName != null) && (collectionValidator != null)) && (string.CompareOrdinal(collectionValidator.ItemTypeNameFromCollection, typeName) == 0))
            {
                typeName = null;
            }
            SerializationTypeNameAnnotation annotation = complexValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (annotation != null)
            {
                typeName = annotation.TypeName;
            }
            if (typeName != null)
            {
                base.JsonWriter.WriteName("__metadata");
                base.JsonWriter.StartObjectScope();
                base.JsonWriter.WriteName("type");
                base.JsonWriter.WriteValue(typeName);
                base.JsonWriter.EndObjectScope();
            }
            this.WriteProperties((type == null) ? null : type.ComplexDefinition(), complexValue.Properties, true, duplicatePropertyNamesChecker, null);
            base.JsonWriter.EndObjectScope();
            this.DecreaseRecursionDepth();
        }
        internal void WriteCollectionValue(ODataCollectionValue collectionValue, IEdmTypeReference metadataTypeReference, bool isOpenPropertyType)
        {
            this.IncreaseRecursionDepth();
            base.JsonWriter.StartObjectScope();
            string typeName = collectionValue.TypeName;
            IEdmCollectionTypeReference type  = (IEdmCollectionTypeReference)WriterValidationUtils.ResolveTypeNameForWriting(base.Model, metadataTypeReference, ref typeName, EdmTypeKind.Collection, isOpenPropertyType);
            string itemTypeNameFromCollection = null;

            if (typeName != null)
            {
                itemTypeNameFromCollection = ValidationUtils.ValidateCollectionTypeName(typeName);
            }
            SerializationTypeNameAnnotation annotation = collectionValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (annotation != null)
            {
                typeName = annotation.TypeName;
            }
            if (typeName != null)
            {
                base.JsonWriter.WriteName("__metadata");
                base.JsonWriter.StartObjectScope();
                base.JsonWriter.WriteName("type");
                base.JsonWriter.WriteValue(typeName);
                base.JsonWriter.EndObjectScope();
            }
            base.JsonWriter.WriteDataArrayName();
            base.JsonWriter.StartArrayScope();
            IEnumerable items = collectionValue.Items;

            if (items != null)
            {
                IEdmTypeReference propertyTypeReference = (type == null) ? null : type.ElementType();
                CollectionWithoutExpectedTypeValidator collectionValidator           = new CollectionWithoutExpectedTypeValidator(itemTypeNameFromCollection);
                DuplicatePropertyNamesChecker          duplicatePropertyNamesChecker = null;
                foreach (object obj2 in items)
                {
                    ValidationUtils.ValidateCollectionItem(obj2, false);
                    ODataComplexValue complexValue = obj2 as ODataComplexValue;
                    if (complexValue != null)
                    {
                        if (duplicatePropertyNamesChecker == null)
                        {
                            duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker();
                        }
                        this.WriteComplexValue(complexValue, propertyTypeReference, false, duplicatePropertyNamesChecker, collectionValidator);
                        duplicatePropertyNamesChecker.Clear();
                    }
                    else
                    {
                        this.WritePrimitiveValue(obj2, collectionValidator, propertyTypeReference);
                    }
                }
            }
            base.JsonWriter.EndArrayScope();
            base.JsonWriter.EndObjectScope();
            this.DecreaseRecursionDepth();
        }
示例#3
0
        private void WriteCollectionValue(ODataCollectionValue collectionValue, IEdmTypeReference propertyTypeReference, bool isOpenPropertyType, bool isWritingCollection)
        {
            this.IncreaseRecursionDepth();
            string typeName = collectionValue.TypeName;
            IEdmCollectionTypeReference type  = (IEdmCollectionTypeReference)WriterValidationUtils.ResolveTypeNameForWriting(base.Model, propertyTypeReference, ref typeName, EdmTypeKind.Collection, isOpenPropertyType);
            string itemTypeNameFromCollection = null;

            if (typeName != null)
            {
                itemTypeNameFromCollection = ValidationUtils.ValidateCollectionTypeName(typeName);
            }
            SerializationTypeNameAnnotation annotation = collectionValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (annotation != null)
            {
                typeName = annotation.TypeName;
            }
            if (typeName != null)
            {
                this.WritePropertyTypeAttribute(typeName);
            }
            IEdmTypeReference metadataTypeReference = (type == null) ? null : type.ElementType();
            CollectionWithoutExpectedTypeValidator collectionValidator = new CollectionWithoutExpectedTypeValidator(itemTypeNameFromCollection);
            IEnumerable items = collectionValue.Items;

            if (items != null)
            {
                DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = null;
                foreach (object obj2 in items)
                {
                    ValidationUtils.ValidateCollectionItem(obj2, false);
                    base.XmlWriter.WriteStartElement("d", "element", base.MessageWriterSettings.WriterBehavior.ODataNamespace);
                    ODataComplexValue complexValue = obj2 as ODataComplexValue;
                    if (complexValue != null)
                    {
                        if (duplicatePropertyNamesChecker == null)
                        {
                            duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker();
                        }
                        this.WriteComplexValue(complexValue, metadataTypeReference, false, isWritingCollection, null, null, duplicatePropertyNamesChecker, collectionValidator, null, null, null);
                        duplicatePropertyNamesChecker.Clear();
                    }
                    else
                    {
                        this.WritePrimitiveValue(obj2, collectionValidator, metadataTypeReference);
                    }
                    base.XmlWriter.WriteEndElement();
                }
            }
            this.DecreaseRecursionDepth();
        }
        /// <summary>
        /// Writes out the value of a collection property.
        /// </summary>
        /// <param name="collectionValue">The collection value to write.</param>
        /// <param name="metadataTypeReference">The metadata type reference for the collection.</param>
        /// <param name="isOpenPropertyType">true if the type name belongs to an open property.</param>
        /// <remarks>The current recursion depth is measured by the number of complex and collection values between
        /// this one and the top-level payload, not including this one.</remarks>
        internal void WriteCollectionValue(
            ODataCollectionValue collectionValue,
            IEdmTypeReference metadataTypeReference,
            bool isOpenPropertyType)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(collectionValue != null, "collectionValue != null");

            this.IncreaseRecursionDepth();

            // Start the object scope which will represent the entire CollectionValue instance
            this.JsonWriter.StartObjectScope();

            // "__metadata": { "type": "typename" }
            // If the CollectionValue has type information write out the metadata and the type in it.
            string typeName = collectionValue.TypeName;

            // resolve the type name to the type; if no type name is specified we will use the
            // type inferred from metadata
            IEdmCollectionTypeReference collectionTypeReference =
                (IEdmCollectionTypeReference)WriterValidationUtils.ResolveTypeNameForWriting(this.Model, metadataTypeReference, ref typeName, EdmTypeKind.Collection, isOpenPropertyType);

            string collectionItemTypeName = null;

            if (typeName != null)
            {
                collectionItemTypeName = ValidationUtils.ValidateCollectionTypeName(typeName);
            }

            SerializationTypeNameAnnotation serializationTypeNameAnnotation = collectionValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (serializationTypeNameAnnotation != null)
            {
                typeName = serializationTypeNameAnnotation.TypeName;
            }

            if (typeName != null)
            {
                // Write the __metadata object
                this.JsonWriter.WriteName(JsonConstants.ODataMetadataName);
                this.JsonWriter.StartObjectScope();

                // "type": "typename"
                this.JsonWriter.WriteName(JsonConstants.ODataMetadataTypeName);
                this.JsonWriter.WriteValue(typeName);

                // End the __metadata
                this.JsonWriter.EndObjectScope();
            }

            // "results": [
            // This represents the array of items in the CollectionValue
            this.JsonWriter.WriteDataArrayName();
            this.JsonWriter.StartArrayScope();

            // Iterate through the CollectionValue items and write them out (treat null Items as an empty enumeration)
            IEnumerable items = collectionValue.Items;

            if (items != null)
            {
                IEdmTypeReference expectedItemTypeReference = collectionTypeReference == null ? null : collectionTypeReference.ElementType();

                CollectionWithoutExpectedTypeValidator collectionValidator = new CollectionWithoutExpectedTypeValidator(collectionItemTypeName);

                DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = null;
                foreach (object item in items)
                {
                    ValidationUtils.ValidateCollectionItem(item, false /* isStreamable */);

                    ODataComplexValue itemAsComplexValue = item as ODataComplexValue;
                    if (itemAsComplexValue != null)
                    {
                        if (duplicatePropertyNamesChecker == null)
                        {
                            duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();
                        }

                        this.WriteComplexValue(
                            itemAsComplexValue,
                            expectedItemTypeReference,
                            false,
                            duplicatePropertyNamesChecker,
                            collectionValidator);

                        duplicatePropertyNamesChecker.Clear();
                    }
                    else
                    {
                        Debug.Assert(!(item is ODataCollectionValue), "!(item is ODataCollectionValue)");
                        Debug.Assert(!(item is ODataStreamReferenceValue), "!(item is ODataStreamReferenceValue)");

                        this.WritePrimitiveValue(item, collectionValidator, expectedItemTypeReference);
                    }
                }
            }

            // End the array scope which holds the items
            this.JsonWriter.EndArrayScope();

            // End the object scope which holds the entire collection
            this.JsonWriter.EndObjectScope();

            this.DecreaseRecursionDepth();
        }
        /// <summary>
        /// Writes out the value of a complex property.
        /// </summary>
        /// <param name="complexValue">The complex value to write.</param>
        /// <param name="propertyTypeReference">The metadata type for the complex value.</param>
        /// <param name="isOpenPropertyType">true if the type name belongs to an open property.</param>
        /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param>
        /// <param name="collectionValidator">The collection validator instance to validate the type names and type kinds of collection items; null if no validation is needed.</param>
        /// <remarks>The current recursion depth should be a value, measured by the number of complex and collection values between
        /// this complex value and the top-level payload, not including this one.</remarks>
        internal void WriteComplexValue(
            ODataComplexValue complexValue,
            IEdmTypeReference propertyTypeReference,
            bool isOpenPropertyType,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            CollectionWithoutExpectedTypeValidator collectionValidator)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(complexValue != null, "complexValue != null");

            this.IncreaseRecursionDepth();

            // Start the object scope which will represent the entire complex instance
            this.JsonWriter.StartObjectScope();

            // Write the "__metadata" : { "type": "typename" }
            // But only if we actually have a typename to write, otherwise we need the __metadata to be omitted entirely
            string typeName = complexValue.TypeName;

            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(typeName, EdmTypeKind.Complex);
            }

            // resolve the type name to the type; if no type name is specified we will use the
            // type inferred from metadata
            IEdmComplexTypeReference complexValueTypeReference =
                WriterValidationUtils.ResolveTypeNameForWriting(this.Model, propertyTypeReference, ref typeName, EdmTypeKind.Complex, isOpenPropertyType).AsComplexOrNull();

            // If the type is the same as the one specified by the parent collection, omit the type name, since it's not needed.
            if (typeName != null && collectionValidator != null)
            {
                string expectedItemTypeName = collectionValidator.ItemTypeNameFromCollection;
                if (string.CompareOrdinal(expectedItemTypeName, typeName) == 0)
                {
                    typeName = null;
                }
            }

            SerializationTypeNameAnnotation serializationTypeNameAnnotation = complexValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (serializationTypeNameAnnotation != null)
            {
                typeName = serializationTypeNameAnnotation.TypeName;
            }

            if (typeName != null)
            {
                // Write the __metadata object
                this.JsonWriter.WriteName(JsonConstants.ODataMetadataName);
                this.JsonWriter.StartObjectScope();

                // "type": "typename"
                this.JsonWriter.WriteName(JsonConstants.ODataMetadataTypeName);
                this.JsonWriter.WriteValue(typeName);

                // End the __metadata
                this.JsonWriter.EndObjectScope();
            }

            // Write the properties of the complex value as usual. Note we do not allow complex types to contain named stream properties.
            this.WriteProperties(
                complexValueTypeReference == null ? null : complexValueTypeReference.ComplexDefinition(),
                complexValue.Properties,
                true /* isComplexValue */,
                duplicatePropertyNamesChecker,
                null /*projectedProperties */);

            // End the object scope which represents the complex instance
            this.JsonWriter.EndObjectScope();

            this.DecreaseRecursionDepth();
        }
示例#6
0
        internal bool WriteComplexValue(ODataComplexValue complexValue, IEdmTypeReference metadataTypeReference, bool isOpenPropertyType, bool isWritingCollection, Action beforeValueAction, Action afterValueAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)
        {
            Action action2  = null;
            string typeName = complexValue.TypeName;

            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(typeName, EdmTypeKind.Complex);
            }
            this.IncreaseRecursionDepth();
            IEdmComplexTypeReference reference = WriterValidationUtils.ResolveTypeNameForWriting(base.Model, metadataTypeReference, ref typeName, EdmTypeKind.Complex, isOpenPropertyType).AsComplexOrNull();

            if (((typeName != null) && (collectionValidator != null)) && (string.CompareOrdinal(collectionValidator.ItemTypeNameFromCollection, typeName) == 0))
            {
                typeName = null;
            }
            SerializationTypeNameAnnotation annotation = complexValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (annotation != null)
            {
                typeName = annotation.TypeName;
            }
            Action beforePropertiesAction = beforeValueAction;

            if (typeName != null)
            {
                if (beforeValueAction != null)
                {
                    if (action2 == null)
                    {
                        action2 = delegate {
                            beforeValueAction();
                            this.WritePropertyTypeAttribute(typeName);
                        };
                    }
                    beforePropertiesAction = action2;
                }
                else
                {
                    this.WritePropertyTypeAttribute(typeName);
                }
            }
            if (((base.MessageWriterSettings.WriterBehavior != null) && base.MessageWriterSettings.WriterBehavior.UseV1ProviderBehavior) && !object.ReferenceEquals(projectedProperties, ProjectedPropertiesAnnotation.EmptyProjectedPropertiesMarker))
            {
                IEdmComplexType definition = (IEdmComplexType)reference.Definition;
                if (base.Model.EpmCachedKeepPrimitiveInContent(definition) == null)
                {
                    List <string> keptInContentPropertyNames = null;
                    foreach (IEdmProperty property in from p in definition.Properties()
                             where p.Type.IsODataPrimitiveTypeKind()
                             select p)
                    {
                        EntityPropertyMappingAttribute entityPropertyMapping = EpmWriterUtils.GetEntityPropertyMapping(epmSourcePathSegment, property.Name);
                        if ((entityPropertyMapping != null) && entityPropertyMapping.KeepInContent)
                        {
                            if (keptInContentPropertyNames == null)
                            {
                                keptInContentPropertyNames = new List <string>();
                            }
                            keptInContentPropertyNames.Add(property.Name);
                        }
                    }
                    base.Model.SetAnnotationValue <CachedPrimitiveKeepInContentAnnotation>(definition, new CachedPrimitiveKeepInContentAnnotation(keptInContentPropertyNames));
                }
            }
            bool flag = this.WriteProperties((reference == null) ? null : reference.ComplexDefinition(), EpmValueCache.GetComplexValueProperties(epmValueCache, complexValue, true), isWritingCollection, beforePropertiesAction, afterValueAction, duplicatePropertyNamesChecker, epmValueCache, epmSourcePathSegment, projectedProperties);

            this.DecreaseRecursionDepth();
            return(flag);
        }
示例#7
0
        /// <summary>
        /// Write the items of a collection in ATOM format.
        /// </summary>
        /// <param name="collectionValue">The collection value to write.</param>
        /// <param name="propertyTypeReference">The type reference of the collection (or null if not metadata is available).</param>
        /// <param name="isOpenPropertyType">true if the type name belongs to an open property.</param>
        /// <param name="isWritingCollection">true if we are writing a collection instead of an entry.</param>
        private void WriteCollectionValue(
            ODataCollectionValue collectionValue,
            IEdmTypeReference propertyTypeReference,
            bool isOpenPropertyType,
            bool isWritingCollection)
        {
            Debug.Assert(collectionValue != null, "collectionValue != null");

            this.IncreaseRecursionDepth();

            string typeName = collectionValue.TypeName;

            // resolve the type name to the type; if no type name is specified we will use the
            // type inferred from metadata
            IEdmCollectionTypeReference collectionTypeReference =
                (IEdmCollectionTypeReference)WriterValidationUtils.ResolveTypeNameForWriting(this.Model, propertyTypeReference, ref typeName, EdmTypeKind.Collection, isOpenPropertyType);

            string collectionItemTypeName = null;

            if (typeName != null)
            {
                collectionItemTypeName = ValidationUtils.ValidateCollectionTypeName(typeName);
            }

            SerializationTypeNameAnnotation serializationTypeNameAnnotation = collectionValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (serializationTypeNameAnnotation != null)
            {
                typeName = serializationTypeNameAnnotation.TypeName;
            }

            if (typeName != null)
            {
                this.WritePropertyTypeAttribute(typeName);
            }

            IEdmTypeReference expectedItemTypeReference = collectionTypeReference == null ? null : collectionTypeReference.ElementType();

            CollectionWithoutExpectedTypeValidator collectionValidator = new CollectionWithoutExpectedTypeValidator(collectionItemTypeName);

            IEnumerable items = collectionValue.Items;

            if (items != null)
            {
                DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = null;
                foreach (object item in items)
                {
                    ValidationUtils.ValidateCollectionItem(item, false /* isStreamable */);

                    this.XmlWriter.WriteStartElement(AtomConstants.ODataNamespacePrefix, AtomConstants.ODataCollectionItemElementName, this.MessageWriterSettings.WriterBehavior.ODataNamespace);
                    ODataComplexValue complexValue = item as ODataComplexValue;
                    if (complexValue != null)
                    {
                        if (duplicatePropertyNamesChecker == null)
                        {
                            duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();
                        }

                        this.WriteComplexValue(
                            complexValue,
                            expectedItemTypeReference,
                            false,
                            isWritingCollection,
                            null /* beforeValueAction */,
                            null /* afterValueAction */,
                            duplicatePropertyNamesChecker,
                            collectionValidator,
                            null /* epmValueCache */,
                            null /* epmSourcePathSegment */,
                            null /* projectedProperties */);

                        duplicatePropertyNamesChecker.Clear();
                    }
                    else
                    {
                        Debug.Assert(!(item is ODataCollectionValue), "!(item is ODataCollectionValue)");
                        Debug.Assert(!(item is ODataStreamReferenceValue), "!(item is ODataStreamReferenceValue)");

                        this.WritePrimitiveValue(item, collectionValidator, expectedItemTypeReference);
                    }

                    this.XmlWriter.WriteEndElement();
                }
            }

            this.DecreaseRecursionDepth();
        }
示例#8
0
        internal bool WriteComplexValue(
            ODataComplexValue complexValue,
            IEdmTypeReference metadataTypeReference,
            bool isOpenPropertyType,
            bool isWritingCollection,
            Action beforeValueAction,
            Action afterValueAction,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            CollectionWithoutExpectedTypeValidator collectionValidator,
            EpmValueCache epmValueCache,
            EpmSourcePathSegment epmSourcePathSegment,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(complexValue != null, "complexValue != null");

            string typeName = complexValue.TypeName;

            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(typeName, EdmTypeKind.Complex);
            }

            this.IncreaseRecursionDepth();

            // resolve the type name to the type; if no type name is specified we will use the
            // type inferred from metadata
            IEdmComplexTypeReference complexTypeReference =
                WriterValidationUtils.ResolveTypeNameForWriting(this.Model, metadataTypeReference, ref typeName, EdmTypeKind.Complex, isOpenPropertyType).AsComplexOrNull();

            // If the type is the same as the one specified by the parent collection, omit the type name, since it's not needed.
            if (typeName != null && collectionValidator != null)
            {
                string expectedItemTypeName = collectionValidator.ItemTypeNameFromCollection;
                if (string.CompareOrdinal(expectedItemTypeName, typeName) == 0)
                {
                    typeName = null;
                }
            }

            SerializationTypeNameAnnotation serializationTypeNameAnnotation = complexValue.GetAnnotation <SerializationTypeNameAnnotation>();

            if (serializationTypeNameAnnotation != null)
            {
                typeName = serializationTypeNameAnnotation.TypeName;
            }

            Action beforeValueCallbackWithTypeName = beforeValueAction;

            if (typeName != null)
            {
                // The beforeValueAction (if specified) will write the actual property element start.
                // So if we are to write the type attribute, we must postpone that after the start element was written.
                // And so we chain the existing action with our type attribute writing and use that
                // as the before action instead.
                if (beforeValueAction != null)
                {
                    beforeValueCallbackWithTypeName = () =>
                    {
                        beforeValueAction();
                        this.WritePropertyTypeAttribute(typeName);
                    };
                }
                else
                {
                    this.WritePropertyTypeAttribute(typeName);
                }
            }

            // NOTE: see the comments on ODataWriterBehavior.UseV1ProviderBehavior for more information
            // NOTE: We have to check for ProjectedPropertiesAnnotation.Empty here to avoid filling the cache for
            //       complex values we are writing only to ensure we don't have nested EPM-mapped null values
            //       that will end up in the content eventually.
            if (this.MessageWriterSettings.WriterBehavior != null &&
                this.MessageWriterSettings.WriterBehavior.UseV1ProviderBehavior &&
                !object.ReferenceEquals(projectedProperties, ProjectedPropertiesAnnotation.EmptyProjectedPropertiesMarker))
            {
                IEdmComplexType complexType = (IEdmComplexType)complexTypeReference.Definition;
                CachedPrimitiveKeepInContentAnnotation keepInContentCache = this.Model.EpmCachedKeepPrimitiveInContent(complexType);
                if (keepInContentCache == null)
                {
                    // we are about to write the first value of the given type; compute the keep-in-content information for the primitive properties of this type.
                    List <string> keepInContentPrimitiveProperties = null;

                    // initialize the cache with all primitive properties
                    foreach (IEdmProperty edmProperty in complexType.Properties().Where(p => p.Type.IsODataPrimitiveTypeKind()))
                    {
                        // figure out the keep-in-content value
                        EntityPropertyMappingAttribute entityPropertyMapping = EpmWriterUtils.GetEntityPropertyMapping(epmSourcePathSegment, edmProperty.Name);
                        if (entityPropertyMapping != null && entityPropertyMapping.KeepInContent)
                        {
                            if (keepInContentPrimitiveProperties == null)
                            {
                                keepInContentPrimitiveProperties = new List <string>();
                            }

                            keepInContentPrimitiveProperties.Add(edmProperty.Name);
                        }
                    }

                    this.Model.SetAnnotationValue <CachedPrimitiveKeepInContentAnnotation>(complexType, new CachedPrimitiveKeepInContentAnnotation(keepInContentPrimitiveProperties));
                }
            }

            bool propertyWritten = this.WriteProperties(
                complexTypeReference == null ? null : complexTypeReference.ComplexDefinition(),
                EpmValueCache.GetComplexValueProperties(epmValueCache, complexValue, true),
                isWritingCollection,
                beforeValueCallbackWithTypeName,
                afterValueAction,
                duplicatePropertyNamesChecker,
                epmValueCache,
                epmSourcePathSegment,
                projectedProperties);

            this.DecreaseRecursionDepth();
            return(propertyWritten);
        }
示例#9
0
        /// <summary>
        /// Reads a property value starting with the specified index to the property value path.
        /// </summary>
        /// <param name="epmInfo">The EPM info which describes the mapping for which to read the property value.</param>
        /// <param name="cachedProperties">The enumeration of properties to search for the first property in the property value path.</param>
        /// <param name="sourceSegmentIndex">The index in the property value path to start with.</param>
        /// <param name="structuredTypeReference">The type of the entry or complex value the <paramref name="cachedProperties"/> enumeration belongs to.</param>
        /// <param name="epmValueCache">The EPM value cache to use.</param>
        /// <returns>The value of the property (may be null), or null if the property itself was not found due to one of its parent properties being null.</returns>
        private object ReadPropertyValue(
            EntityPropertyMappingInfo epmInfo,
            IEnumerable <ODataProperty> cachedProperties,
            int sourceSegmentIndex,
            IEdmStructuredTypeReference structuredTypeReference,
            EpmValueCache epmValueCache)
        {
            Debug.Assert(epmInfo != null, "epmInfo != null");
            Debug.Assert(epmInfo.PropertyValuePath != null, "The PropertyValuePath should have been initialized by now.");
            Debug.Assert(epmInfo.PropertyValuePath.Length > sourceSegmentIndex, "The PropertyValuePath must be at least as long as the source segment index.");
            Debug.Assert(structuredTypeReference != null, "structuredTypeReference != null");
            Debug.Assert(epmValueCache != null, "epmValueCache != null");

            EpmSourcePathSegment sourceSegment = epmInfo.PropertyValuePath[sourceSegmentIndex];
            string propertyName = sourceSegment.PropertyName;
            bool   lastSegment  = epmInfo.PropertyValuePath.Length == sourceSegmentIndex + 1;

            IEdmStructuredType structuredType = structuredTypeReference.StructuredDefinition();
            IEdmProperty       edmProperty    = WriterValidationUtils.ValidatePropertyDefined(propertyName, structuredType);

            if (edmProperty != null)
            {
                // If this is the last part of the path, then it has to be a primitive or atomic collection type otherwise should be a complex type
                if (lastSegment)
                {
                    if (!edmProperty.Type.IsODataPrimitiveTypeKind() && !edmProperty.Type.IsNonEntityODataCollectionTypeKind())
                    {
                        throw new ODataException(o.Strings.EpmSourceTree_EndsWithNonPrimitiveType(propertyName));
                    }
                }
                else
                {
                    if (edmProperty.Type.TypeKind() != EdmTypeKind.Complex)
                    {
                        throw new ODataException(o.Strings.EpmSourceTree_TraversalOfNonComplexType(propertyName));
                    }
                }
            }
            else
            {
                Debug.Assert(
                    structuredType.IsOpen,
                    "Only open types can have undeclared properties, otherwise we should have failed in the ValidatePropertyDefined method.");
            }

            ODataProperty property = cachedProperties == null ? null : cachedProperties.FirstOrDefault(p => p.Name == propertyName);

            if (property == null)
            {
                throw new ODataException(o.Strings.EpmSourceTree_MissingPropertyOnInstance(propertyName, structuredTypeReference.ODataFullName()));
            }

            object            propertyValue        = property.Value;
            ODataComplexValue propertyComplexValue = propertyValue as ODataComplexValue;

            if (lastSegment)
            {
                if (propertyValue == null)
                {
                    WriterValidationUtils.ValidateNullPropertyValue(edmProperty, this.WriterBehavior, this.atomOutputContext.Model);
                }
                else
                {
                    // If this property is the last one it has to be either a primitive or collection
                    if (propertyComplexValue != null)
                    {
                        throw new ODataException(o.Strings.EpmSourceTree_EndsWithNonPrimitiveType(propertyName));
                    }
                    else
                    {
                        ODataCollectionValue propertyCollectionValue = propertyValue as ODataCollectionValue;
                        if (propertyCollectionValue != null)
                        {
                            // Validate the type name for the collection
                            string typeName = propertyCollectionValue.TypeName;
                            WriterValidationUtils.ResolveTypeNameForWriting(
                                this.atomOutputContext.Model,
                                edmProperty == null ? null : edmProperty.Type,
                                ref typeName,
                                EdmTypeKind.Collection,
                                edmProperty == null);
                        }
                        else
                        {
                            if (propertyValue is ODataStreamReferenceValue)
                            {
                                // Stream properties should not come here, if it were an ODataEntry property it would have been
                                // filtered in ReadEntryPropertyValue() by "epmValueCache.EntryProperties" call.
                                throw new ODataException(o.Strings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
                            }
                            else if (propertyValue is ISpatial)
                            {
                                throw new ODataException(o.Strings.EpmSourceTree_OpenPropertySpatialTypeCannotBeMapped(propertyName, epmInfo.DefiningType.FullName()));
                            }
                            else if (edmProperty != null)
                            {
                                ValidationUtils.ValidateIsExpectedPrimitiveType(propertyValue, edmProperty.Type);
                            }
                        }
                    }
                }

                return(propertyValue);
            }

            // Otherwise it's in the middle and thus it must be a complex value
            if (propertyComplexValue == null)
            {
                if (propertyValue != null)
                {
                    // It's not a complex value - fail.
                    throw new ODataException(o.Strings.EpmSourceTree_TraversalOfNonComplexType(propertyName));
                }
                else
                {
                    // The value of the property is null, which can be a null complex value
                    // Note that we must not attempt to resolve the type as if the type name was null here, because
                    //  1) We don't need the type for anything anyway (the value is null, this is the end)
                    //  2) If the property is open, trying to resolve a null type name would throw
                    //     but we don't have a null type name, we have a null entire value.
                    return(null);
                }
            }

            string localTypeName = propertyComplexValue.TypeName;
            IEdmComplexTypeReference complexValueType = WriterValidationUtils.ResolveTypeNameForWriting(
                this.atomOutputContext.Model,
                edmProperty == null ? null : edmProperty.Type,
                ref localTypeName,
                EdmTypeKind.Complex,
                edmProperty == null).AsComplexOrNull();

            return(this.ReadComplexPropertyValue(
                       epmInfo,
                       propertyComplexValue,
                       epmValueCache,
                       sourceSegmentIndex + 1,
                       complexValueType));
        }
示例#10
0
        private object ReadPropertyValue(EntityPropertyMappingInfo epmInfo, IEnumerable <ODataProperty> cachedProperties, int sourceSegmentIndex, IEdmStructuredTypeReference structuredTypeReference, EpmValueCache epmValueCache)
        {
            EpmSourcePathSegment segment            = epmInfo.PropertyValuePath[sourceSegmentIndex];
            string             propertyName         = segment.PropertyName;
            bool               flag                 = epmInfo.PropertyValuePath.Length == (sourceSegmentIndex + 1);
            IEdmStructuredType owningStructuredType = structuredTypeReference.StructuredDefinition();
            IEdmProperty       expectedProperty     = WriterValidationUtils.ValidatePropertyDefined(propertyName, owningStructuredType);

            if (expectedProperty != null)
            {
                if (flag)
                {
                    if (!expectedProperty.Type.IsODataPrimitiveTypeKind() && !expectedProperty.Type.IsNonEntityODataCollectionTypeKind())
                    {
                        throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_EndsWithNonPrimitiveType(propertyName));
                    }
                }
                else if (expectedProperty.Type.TypeKind() != EdmTypeKind.Complex)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_TraversalOfNonComplexType(propertyName));
                }
            }
            ODataProperty property2 = (cachedProperties == null) ? null : cachedProperties.FirstOrDefault <ODataProperty>(p => (p.Name == propertyName));

            if (property2 == null)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_MissingPropertyOnInstance(propertyName, structuredTypeReference.ODataFullName()));
            }
            object            obj2         = property2.Value;
            ODataComplexValue complexValue = obj2 as ODataComplexValue;

            if (flag)
            {
                if (obj2 == null)
                {
                    WriterValidationUtils.ValidateNullPropertyValue(expectedProperty, this.WriterBehavior, this.atomOutputContext.Model);
                    return(obj2);
                }
                if (complexValue != null)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_EndsWithNonPrimitiveType(propertyName));
                }
                ODataCollectionValue value3 = obj2 as ODataCollectionValue;
                if (value3 != null)
                {
                    string str = value3.TypeName;
                    WriterValidationUtils.ResolveTypeNameForWriting(this.atomOutputContext.Model, (expectedProperty == null) ? null : expectedProperty.Type, ref str, EdmTypeKind.Collection, expectedProperty == null);
                    return(obj2);
                }
                if (obj2 is ODataStreamReferenceValue)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
                }
                if (obj2 is ISpatial)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_OpenPropertySpatialTypeCannotBeMapped(propertyName, epmInfo.DefiningType.FullName()));
                }
                if (expectedProperty != null)
                {
                    ValidationUtils.ValidateIsExpectedPrimitiveType(obj2, expectedProperty.Type);
                }
                return(obj2);
            }
            if (complexValue == null)
            {
                if (obj2 != null)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_TraversalOfNonComplexType(propertyName));
                }
                return(null);
            }
            string typeName = complexValue.TypeName;
            IEdmComplexTypeReference complexType = WriterValidationUtils.ResolveTypeNameForWriting(this.atomOutputContext.Model, (expectedProperty == null) ? null : expectedProperty.Type, ref typeName, EdmTypeKind.Complex, expectedProperty == null).AsComplexOrNull();

            return(this.ReadComplexPropertyValue(epmInfo, complexValue, epmValueCache, sourceSegmentIndex + 1, complexType));
        }