private bool ShouldWritePropertyInContent(IEdmStructuredType owningType, ProjectedPropertiesAnnotation projectedProperties, string propertyName, object propertyValue, EpmSourcePathSegment epmSourcePathSegment)
 {
     bool flag = !projectedProperties.ShouldSkipProperty(propertyName);
     if ((((base.MessageWriterSettings.WriterBehavior != null) && base.MessageWriterSettings.WriterBehavior.UseV1ProviderBehavior) && (owningType != null)) && owningType.IsODataComplexTypeKind())
     {
         IEdmComplexType complexType = (IEdmComplexType) owningType;
         CachedPrimitiveKeepInContentAnnotation annotation = base.Model.EpmCachedKeepPrimitiveInContent(complexType);
         if ((annotation != null) && annotation.IsKeptInContent(propertyName))
         {
             return flag;
         }
     }
     if ((propertyValue == null) && (epmSourcePathSegment != null))
     {
         return true;
     }
     EntityPropertyMappingAttribute entityPropertyMapping = EpmWriterUtils.GetEntityPropertyMapping(epmSourcePathSegment);
     if (entityPropertyMapping == null)
     {
         return flag;
     }
     string str = propertyValue as string;
     if ((str != null) && (str.Length == 0))
     {
         switch (entityPropertyMapping.TargetSyndicationItem)
         {
             case SyndicationItemProperty.AuthorEmail:
             case SyndicationItemProperty.AuthorUri:
             case SyndicationItemProperty.ContributorEmail:
             case SyndicationItemProperty.ContributorUri:
                 return true;
         }
     }
     return (entityPropertyMapping.KeepInContent && flag);
 }
 internal void WriteAssociationLink(ODataAssociationLink associationLink, IEdmEntityType owningType, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties)
 {
     ValidationUtils.ValidateAssociationLinkNotNull(associationLink);
     if (!projectedProperties.ShouldSkipProperty(associationLink.Name))
     {
         base.ValidateAssociationLink(associationLink, owningType);
         duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(associationLink);
         AtomLinkMetadata annotation = associationLink.GetAnnotation<AtomLinkMetadata>();
         string relation = AtomUtils.ComputeODataAssociationLinkRelation(associationLink);
         AtomLinkMetadata linkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(annotation, relation, associationLink.Url, associationLink.Name, "application/xml");
         this.atomEntryMetadataSerializer.WriteAtomLink(linkMetadata, null);
     }
 }
Example #3
0
        private void EnterScope(WriterState newState, ODataItem item)
        {
            this.InterceptException(() => this.ValidateTransition(newState));
            bool  skipWriting  = this.SkipWriting;
            Scope currentScope = this.CurrentScope;

            if (((currentScope.State == WriterState.Entry) && (newState == WriterState.NavigationLink)) && !skipWriting)
            {
                ProjectedPropertiesAnnotation projectedProperties = currentScope.Item.GetAnnotation <ProjectedPropertiesAnnotation>();
                ODataNavigationLink           link = (ODataNavigationLink)item;
                skipWriting = projectedProperties.ShouldSkipProperty(link.Name);
            }
            else if ((currentScope.State == WriterState.Feed) && (newState == WriterState.Entry))
            {
                FeedScope scope1 = (FeedScope)currentScope;
                scope1.EntryCount++;
            }
            this.PushScope(newState, item, skipWriting);
        }
Example #4
0
 private void WriteEntryContent(ODataEntry entry, IEdmEntityType entryType, EntryPropertiesValueCache propertiesValueCache, EpmSourcePathSegment rootSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)
 {
     ODataStreamReferenceValue mediaResource = entry.MediaResource;
     if (mediaResource == null)
     {
         this.atomOutputContext.XmlWriter.WriteStartElement("", "content", "http://www.w3.org/2005/Atom");
         this.atomOutputContext.XmlWriter.WriteAttributeString("type", "application/xml");
         this.atomEntryAndFeedSerializer.WriteProperties(entryType, propertiesValueCache.EntryProperties, false, new Action(this.atomEntryAndFeedSerializer.WriteEntryPropertiesStart), new Action(this.atomEntryAndFeedSerializer.WriteEntryPropertiesEnd), base.DuplicatePropertyNamesChecker, propertiesValueCache, rootSourcePathSegment, projectedProperties);
         this.atomOutputContext.XmlWriter.WriteEndElement();
     }
     else
     {
         WriterValidationUtils.ValidateStreamReferenceValue(mediaResource, true);
         this.atomEntryAndFeedSerializer.WriteEntryMediaEditLink(mediaResource);
         if (mediaResource.ReadLink != null)
         {
             this.atomOutputContext.XmlWriter.WriteStartElement("", "content", "http://www.w3.org/2005/Atom");
             this.atomOutputContext.XmlWriter.WriteAttributeString("type", mediaResource.ContentType);
             this.atomOutputContext.XmlWriter.WriteAttributeString("src", this.atomEntryAndFeedSerializer.UriToUrlAttributeValue(mediaResource.ReadLink));
             this.atomOutputContext.XmlWriter.WriteEndElement();
         }
         this.atomEntryAndFeedSerializer.WriteProperties(entryType, propertiesValueCache.EntryProperties, false, new Action(this.atomEntryAndFeedSerializer.WriteEntryPropertiesStart), new Action(this.atomEntryAndFeedSerializer.WriteEntryPropertiesEnd), base.DuplicatePropertyNamesChecker, propertiesValueCache, rootSourcePathSegment, projectedProperties);
     }
 }
 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);
                 }
             }
         }
     }
 }
 internal void WriteProperties(IEdmStructuredType owningType, IEnumerable<ODataProperty> properties, bool isComplexValue, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties)
 {
     if (properties != null)
     {
         foreach (ODataProperty property in properties)
         {
             this.WriteProperty(property, owningType, !isComplexValue, duplicatePropertyNamesChecker, projectedProperties);
         }
     }
 }
        /// <summary>
        /// Writes property names and value pairs.
        /// </summary>
        /// <param name="owningType">The <see cref="IEdmStructuredType"/> of the entry (or null if not metadata is available).</param>
        /// <param name="properties">The enumeration of properties to write out.</param>
        /// <param name="isComplexValue">
        /// Whether the properties are being written for complex value. Also used for detecting whether stream properties
        /// are allowed as 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>
        internal void WriteProperties(
            IEdmStructuredType owningType,
            IEnumerable<ODataProperty> properties,
            bool isComplexValue,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();

            if (properties == null)
            {
                return;
            }

            foreach (ODataProperty property in properties)
            {
                this.WriteProperty(
                    property,
                    owningType,
                    !isComplexValue,
                    duplicatePropertyNamesChecker,
                    projectedProperties);
            }
        }
        /// <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);
                        }
                    }
                }
            }
        }
        /// <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;
        }
 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;
 }
 internal bool WriteProperties(IEdmStructuredType owningType, IEnumerable<ODataProperty> cachedProperties, bool isWritingCollection, Action beforePropertiesAction, Action afterPropertiesAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties)
 {
     if (cachedProperties == null)
     {
         return false;
     }
     bool flag = false;
     foreach (ODataProperty property in cachedProperties)
     {
         flag |= this.WriteProperty(property, owningType, false, isWritingCollection, flag ? null : beforePropertiesAction, epmValueCache, epmSourcePathSegment, duplicatePropertyNamesChecker, projectedProperties);
     }
     if ((afterPropertiesAction != null) && flag)
     {
         afterPropertiesAction();
     }
     return flag;
 }
 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;
 }
        /// <summary>
        /// Write the given collection of properties.
        /// </summary>
        /// <param name="owningType">The <see cref="IEdmStructuredType"/> of the entry (or null if not metadata is available).</param>
        /// <param name="cachedProperties">Collection of cached properties for the entry.</param>
        /// <param name="isWritingCollection">true if we are writing a collection instead of an entry.</param>
        /// <param name="beforePropertiesAction">Action which is called before the properties are written, if there are any property.</param>
        /// <param name="afterPropertiesAction">Action which is called after the properties are written, if there are any property.</param>
        /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</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="epmSourcePathSegment">The EPM source path segment which points to the property which sub-properites we're writing. (can be null)</param>
        /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param>
        /// <returns>true if anything was written, false otherwise.</returns>
        internal bool WriteProperties(
            IEdmStructuredType owningType,
            IEnumerable<ODataProperty> cachedProperties,
            bool isWritingCollection,
            Action beforePropertiesAction,
            Action afterPropertiesAction,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            EpmValueCache epmValueCache,
            EpmSourcePathSegment epmSourcePathSegment,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();

            if (cachedProperties == null)
            {
                return false;
            }

            bool propertyWritten = false;
            foreach (ODataProperty property in cachedProperties)
            {
                propertyWritten |= this.WriteProperty(
                    property,
                    owningType,
                    false,
                    isWritingCollection,
                    propertyWritten ? null : beforePropertiesAction,
                    epmValueCache,
                    epmSourcePathSegment,
                    duplicatePropertyNamesChecker,
                    projectedProperties);
            }

            if (afterPropertiesAction != null && propertyWritten)
            {
                afterPropertiesAction();
            }

            return propertyWritten;
        }
        /// <summary>
        /// Determines if the property with the specified value should be written into content or not.
        /// </summary>
        /// <param name="owningType">The owning type of the property to be checked.</param>
        /// <param name="projectedProperties">The set of projected properties for the <paramref name="owningType"/></param>
        /// <param name="propertyName">The name of the property to be checked.</param>
        /// <param name="propertyValue">The property value to write.</param>
        /// <param name="epmSourcePathSegment">The EPM source path segment for the property being written.</param>
        /// <returns>true if the property should be written into content, or false otherwise</returns>
        private bool ShouldWritePropertyInContent(
            IEdmStructuredType owningType,
            ProjectedPropertiesAnnotation projectedProperties,
            string propertyName,
            object propertyValue,
            EpmSourcePathSegment epmSourcePathSegment)
        {
            // check whether the property is projected; if no EPM is specified for the property the projection decides 
            bool propertyProjected = !projectedProperties.ShouldSkipProperty(propertyName);

            bool useV1ProviderBehavior = this.MessageWriterSettings.WriterBehavior == null ? false : this.MessageWriterSettings.WriterBehavior.UseV1ProviderBehavior;
            if (useV1ProviderBehavior && owningType != null && owningType.IsODataComplexTypeKind())
            {
                IEdmComplexType owningComplexType = (IEdmComplexType)owningType;
                CachedPrimitiveKeepInContentAnnotation keepInContentAnnotation = this.Model.EpmCachedKeepPrimitiveInContent(owningComplexType);
                if (keepInContentAnnotation != null && keepInContentAnnotation.IsKeptInContent(propertyName))
                {
                    return propertyProjected;
                }
            }

            // We sometimes write properties into content even if asked not to.
            // If the property value is null and the property (or one of its descendant properties) is mapped, 
            // we always write into content, even if the property was not projected.
            if (propertyValue == null && epmSourcePathSegment != null)
            {
                return true;
            }

            EntityPropertyMappingAttribute entityPropertyMapping = EpmWriterUtils.GetEntityPropertyMapping(epmSourcePathSegment);
            if (entityPropertyMapping == null)
            {
                return propertyProjected;
            }

            string stringPropertyValue = propertyValue as string;
            if (stringPropertyValue != null && stringPropertyValue.Length == 0)
            {
                // If the property value is an empty string and we should be writing it into an ATOM element which does not allow empty string
                // we write it into content as well, also even if the property was not projected.
                switch (entityPropertyMapping.TargetSyndicationItem)
                {
                    case SyndicationItemProperty.AuthorEmail:
                    case SyndicationItemProperty.AuthorUri:
                    case SyndicationItemProperty.ContributorEmail:
                    case SyndicationItemProperty.ContributorUri:
                        return true;

                    default:
                        break;
                }
            }

            return entityPropertyMapping.KeepInContent && propertyProjected;
        }
Example #15
0
        /// <summary>
        /// Write the content of the given entry.
        /// </summary>
        /// <param name="entry">The entry for which to write properties.</param>
        /// <param name="entryType">The <see cref="IEdmEntityType"/> of the entry (or null if not metadata is available).</param>
        /// <param name="propertiesValueCache">The cache of properties.</param>
        /// <param name="rootSourcePathSegment">The root of the EPM source tree, if there's an EPM applied.</param>
        /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param>
        private void WriteEntryContent(
            ODataEntry entry,
            IEdmEntityType entryType, 
            EntryPropertiesValueCache propertiesValueCache, 
            EpmSourcePathSegment rootSourcePathSegment,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            Debug.Assert(entry != null, "entry != null");
            Debug.Assert(propertiesValueCache != null, "propertiesValueCache != null");

            ODataStreamReferenceValue mediaResource = entry.MediaResource;
            if (mediaResource == null)
            {
                // <content type="application/xml">
                this.atomOutputContext.XmlWriter.WriteStartElement(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomContentElementName,
                    AtomConstants.AtomNamespace);

                this.atomOutputContext.XmlWriter.WriteAttributeString(
                    AtomConstants.AtomTypeAttributeName,
                    MimeConstants.MimeApplicationXml);

                this.atomEntryAndFeedSerializer.AssertRecursionDepthIsZero();
                this.atomEntryAndFeedSerializer.WriteProperties(
                    entryType,
                    propertiesValueCache.EntryProperties,
                    false /* isWritingCollection */,
                    this.atomEntryAndFeedSerializer.WriteEntryPropertiesStart,
                    this.atomEntryAndFeedSerializer.WriteEntryPropertiesEnd,
                    this.DuplicatePropertyNamesChecker,
                    propertiesValueCache,
                    rootSourcePathSegment,
                    projectedProperties);
                this.atomEntryAndFeedSerializer.AssertRecursionDepthIsZero();

                // </content>
                this.atomOutputContext.XmlWriter.WriteEndElement();
            }
            else
            {
                WriterValidationUtils.ValidateStreamReferenceValue(mediaResource, true);

                this.atomEntryAndFeedSerializer.WriteEntryMediaEditLink(mediaResource);

                if (mediaResource.ReadLink != null)
                {
                    // <content type="type" src="src">
                    this.atomOutputContext.XmlWriter.WriteStartElement(
                        AtomConstants.AtomNamespacePrefix,
                        AtomConstants.AtomContentElementName,
                        AtomConstants.AtomNamespace);

                    Debug.Assert(!string.IsNullOrEmpty(mediaResource.ContentType), "The default stream content type should have been validated by now. If we have a read link we must have a non-empty content type as well.");
                    this.atomOutputContext.XmlWriter.WriteAttributeString(
                        AtomConstants.AtomTypeAttributeName,
                        mediaResource.ContentType);

                    this.atomOutputContext.XmlWriter.WriteAttributeString(
                        AtomConstants.MediaLinkEntryContentSourceAttributeName,
                        this.atomEntryAndFeedSerializer.UriToUrlAttributeValue(mediaResource.ReadLink));

                    // </content>
                    this.atomOutputContext.XmlWriter.WriteEndElement();
                }

                this.atomEntryAndFeedSerializer.AssertRecursionDepthIsZero();
                this.atomEntryAndFeedSerializer.WriteProperties(
                    entryType,
                    propertiesValueCache.EntryProperties, 
                    false /* isWritingCollection */,
                    this.atomEntryAndFeedSerializer.WriteEntryPropertiesStart,
                    this.atomEntryAndFeedSerializer.WriteEntryPropertiesEnd,
                    this.DuplicatePropertyNamesChecker,
                    propertiesValueCache,
                    rootSourcePathSegment,
                    projectedProperties);
                this.atomEntryAndFeedSerializer.AssertRecursionDepthIsZero();
            }
        }
 internal void WriteStreamProperty(ODataProperty streamProperty, IEdmEntityType owningType, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties)
 {
     WriterValidationUtils.ValidatePropertyNotNull(streamProperty);
     string name = streamProperty.Name;
     if (!projectedProperties.ShouldSkipProperty(name))
     {
         WriterValidationUtils.ValidateProperty(streamProperty);
         duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(streamProperty);
         IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(streamProperty.Name, owningType);
         WriterValidationUtils.ValidateStreamReferenceProperty(streamProperty, edmProperty, base.Version, base.WritingResponse);
         ODataStreamReferenceValue value2 = (ODataStreamReferenceValue) streamProperty.Value;
         if (((owningType != null) && owningType.IsOpen) && (edmProperty == null))
         {
             ValidationUtils.ValidateOpenPropertyValue(streamProperty.Name, value2);
         }
         AtomStreamReferenceMetadata annotation = value2.GetAnnotation<AtomStreamReferenceMetadata>();
         string contentType = value2.ContentType;
         string title = streamProperty.Name;
         Uri readLink = value2.ReadLink;
         if (readLink != null)
         {
             string relation = AtomUtils.ComputeStreamPropertyRelation(streamProperty, false);
             AtomLinkMetadata metadata = (annotation == null) ? null : annotation.SelfLink;
             AtomLinkMetadata linkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(metadata, relation, readLink, title, contentType);
             this.atomEntryMetadataSerializer.WriteAtomLink(linkMetadata, null);
         }
         Uri editLink = value2.EditLink;
         if (editLink != null)
         {
             string str5 = AtomUtils.ComputeStreamPropertyRelation(streamProperty, true);
             AtomLinkMetadata metadata4 = (annotation == null) ? null : annotation.EditLink;
             AtomLinkMetadata metadata5 = ODataAtomWriterMetadataUtils.MergeLinkMetadata(metadata4, str5, editLink, title, contentType);
             this.atomEntryMetadataSerializer.WriteAtomLink(metadata5, value2.ETag);
         }
     }
 }
 internal void WriteEntryMetadata(ODataEntry entry, ProjectedPropertiesAnnotation projectedProperties, IEdmEntityType entryEntityType, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
 {
     base.JsonWriter.WriteName("__metadata");
     base.JsonWriter.StartObjectScope();
     string id = entry.Id;
     if (id != null)
     {
         base.JsonWriter.WriteName("id");
         base.JsonWriter.WriteValue(id);
     }
     Uri uri = entry.EditLink ?? entry.ReadLink;
     if (uri != null)
     {
         base.JsonWriter.WriteName("uri");
         base.JsonWriter.WriteValue(base.UriToAbsoluteUriString(uri));
     }
     string eTag = entry.ETag;
     if (eTag != null)
     {
         base.WriteETag("etag", eTag);
     }
     string typeName = entry.TypeName;
     SerializationTypeNameAnnotation annotation = entry.GetAnnotation<SerializationTypeNameAnnotation>();
     if (annotation != null)
     {
         typeName = annotation.TypeName;
     }
     if (typeName != null)
     {
         base.JsonWriter.WriteName("type");
         base.JsonWriter.WriteValue(typeName);
     }
     ODataStreamReferenceValue mediaResource = entry.MediaResource;
     if (mediaResource != null)
     {
         WriterValidationUtils.ValidateStreamReferenceValue(mediaResource, true);
         base.WriteStreamReferenceValueContent(mediaResource);
     }
     IEnumerable<ODataAction> actions = entry.Actions;
     if (actions != null)
     {
         this.WriteOperations(actions.Cast<ODataOperation>(), true);
     }
     IEnumerable<ODataFunction> functions = entry.Functions;
     if (functions != null)
     {
         this.WriteOperations(functions.Cast<ODataOperation>(), false);
     }
     IEnumerable<ODataAssociationLink> associationLinks = entry.AssociationLinks;
     if (associationLinks != null)
     {
         bool flag = true;
         foreach (ODataAssociationLink link in associationLinks)
         {
             ValidationUtils.ValidateAssociationLinkNotNull(link);
             if (!projectedProperties.ShouldSkipProperty(link.Name))
             {
                 if (flag)
                 {
                     base.JsonWriter.WriteName("properties");
                     base.JsonWriter.StartObjectScope();
                     flag = false;
                 }
                 base.ValidateAssociationLink(link, entryEntityType);
                 this.WriteAssociationLink(link, duplicatePropertyNamesChecker);
             }
         }
         if (!flag)
         {
             base.JsonWriter.EndObjectScope();
         }
     }
     base.JsonWriter.EndObjectScope();
 }
Example #18
0
 internal static bool ShouldSkipProperty(this ProjectedPropertiesAnnotation projectedProperties, string propertyName)
 {
     return((projectedProperties != null) && !projectedProperties.IsPropertyProjected(propertyName));
 }
        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;
        }