/// <summary>
        /// Verifies that the given property name is a valid annotation name, and throws if not.
        /// </summary>
        /// <param name="propertyName">The property name to check.</param>
        /// <param name="annotationGroup">The annotation group which this property would be added to.</param>
        private static void VerifyDataPropertyIsAnnotationName(string propertyName, ODataJsonLightAnnotationGroup annotationGroup)
        {
            Debug.Assert(annotationGroup != null, "annotationGroup != null");

            if (!IsAnnotationGroupName(propertyName))
            {
                throw CreateExceptionForInvalidAnnotationInsideAnnotationGroup(propertyName, annotationGroup);
            }
        }
        /// <summary>
        /// Verifies that the name of the given annotation group was set, and throws otherwise.
        /// </summary>
        /// <param name="annotationGroup">The annnotation group to check.</param>
        private static void VerifyAnnotationGroupNameFound(ODataJsonLightAnnotationGroup annotationGroup)
        {
            Debug.Assert(annotationGroup != null, "annotationGroup != null");

            if (string.IsNullOrEmpty(annotationGroup.Name))
            {
                throw new ODataException(Strings.JsonLightAnnotationGroupDeserializer_AnnotationGroupDeclarationWithoutName);
            }
        }
        /// <summary>
        /// Checks to see that the name of the given annotation group has not yet been set. Throws otherwise.
        /// </summary>
        /// <param name="annotationGroup">The annotation group to check.</param>
        private static void VerifyAnnotationGroupNameNotYetFound(ODataJsonLightAnnotationGroup annotationGroup)
        {
            Debug.Assert(annotationGroup != null, "annotaionGroup != null");

            if (!string.IsNullOrEmpty(annotationGroup.Name))
            {
                throw new ODataException(Strings.JsonLightAnnotationGroupDeserializer_EncounteredMultipleNameProperties);
            }
        }
        /// <summary>
        /// Adds the given annotation group to the set of groups which can be retrieved by annotation group references.
        /// </summary>
        /// <param name="annotationGroup">The annotation group to add.</param>
        internal void AddAnnotationGroup(ODataJsonLightAnnotationGroup annotationGroup)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(annotationGroup != null, "annotationGroup != null");

            if (this.annotationGroups.ContainsKey(annotationGroup.Name))
            {
                throw new ODataException(Strings.JsonLightAnnotationGroupDeserializer_MultipleAnnotationGroupsWithSameName(annotationGroup.Name));
            }

            this.annotationGroups.Add(annotationGroup.Name, annotationGroup);
        }
Exemple #5
0
        /// <summary>
        /// Writes an annotation group declaration or annotation group reference if specified for the entry.
        /// </summary>
        /// <param name="entry">The entry to write the annotation group declaration or reference for.</param>
        internal void WriteAnnotationGroup(ODataEntry entry)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(entry != null, "entry != null");

            ODataJsonLightAnnotationGroup annotationGroup = entry.GetAnnotation <ODataJsonLightAnnotationGroup>();

            if (annotationGroup == null)
            {
                return;
            }

            if (!this.JsonLightOutputContext.WritingResponse)
            {
                throw new ODataException(OData.Strings.ODataJsonLightEntryAndFeedSerializer_AnnotationGroupInRequest);
            }

            string annotationGroupName = annotationGroup.Name;

            if (string.IsNullOrEmpty(annotationGroupName))
            {
                throw new ODataException(OData.Strings.ODataJsonLightEntryAndFeedSerializer_AnnotationGroupWithoutName);
            }

            // Check whether this is the first occurrence of the annotation group.
            ODataJsonLightAnnotationGroup existingAnnotationGroup;

            if (this.annotationGroups.TryGetValue(annotationGroupName, out existingAnnotationGroup))
            {
                // Make sure the annotation groups are reference equal if they have the same name.
                if (!object.ReferenceEquals(existingAnnotationGroup, annotationGroup))
                {
                    throw new ODataException(OData.Strings.ODataJsonLightEntryAndFeedSerializer_DuplicateAnnotationGroup(annotationGroupName));
                }

                // Write an annotation group reference
                this.JsonWriter.WriteName(ODataAnnotationNames.ODataAnnotationGroupReference);
                this.JsonWriter.WritePrimitiveValue(annotationGroupName, this.JsonLightOutputContext.Version);
            }
            else
            {
                // Write an annotation group declaration
                this.JsonWriter.WriteName(ODataAnnotationNames.ODataAnnotationGroup);
                this.JsonWriter.StartObjectScope();
                this.JsonWriter.WriteName(JsonLightConstants.ODataAnnotationGroupNamePropertyName);
                this.JsonWriter.WritePrimitiveValue(annotationGroupName, this.JsonLightOutputContext.Version);

                if (annotationGroup.Annotations != null)
                {
                    foreach (KeyValuePair <string, object> kvp in annotationGroup.Annotations)
                    {
                        string annotationKey = kvp.Key;
                        Debug.Assert(annotationKey != null, "annotationKey != null");
                        if (annotationKey.Length == 0)
                        {
                            throw new ODataException(OData.Strings.ODataJsonLightEntryAndFeedSerializer_AnnotationGroupMemberWithoutName(annotationGroup.Name));
                        }

                        if (!ODataJsonLightReaderUtils.IsAnnotationProperty(annotationKey))
                        {
                            throw new ODataException(OData.Strings.ODataJsonLightEntryAndFeedSerializer_AnnotationGroupMemberMustBeAnnotation(annotationKey, annotationGroup.Name));
                        }

                        this.JsonWriter.WriteName(annotationKey);

                        object annotationValue       = kvp.Value;
                        string annotationValueString = annotationValue as string;
                        if (annotationValueString == null && annotationValue != null)
                        {
                            throw new ODataException(OData.Strings.ODataJsonLightEntryAndFeedSerializer_AnnotationGroupMemberWithInvalidValue(annotationKey, annotationGroup.Name, annotationValue.GetType().FullName));
                        }

                        this.JsonWriter.WritePrimitiveValue(annotationValueString, this.JsonLightOutputContext.Version);
                    }
                }

                this.JsonWriter.EndObjectScope();

                // Remember that we wrote the declaration of the annotation group.
                this.annotationGroups.Add(annotationGroupName, annotationGroup);
            }
        }
        /// <summary>
        /// Reads an annotation group declaration and returns a newly created annotation group instance.
        /// </summary>
        /// <param name="readPropertyAnnotationValue">Function which takes the name of an OData property annotation and reads and returns the value of the annotation.</param>
        /// <param name="readInstanceAnnotationValue">Function which takes the name of an OData instance annotation and reads and returns the value of the annotation.</param>
        /// <returns>The annotation group which was read.</returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.StartObject:     The property to consider as an annotion group declaration or reference.
        ///                 Any:                          Any other node type will throw an exception.
        /// Post-Condition: Any:                          The node after the annotation group property value.
        /// </remarks>
        private ODataJsonLightAnnotationGroup ReadAnnotationGroupDeclaration(Func <string, object> readPropertyAnnotationValue, Func <string, DuplicatePropertyNamesChecker, object> readInstanceAnnotationValue)
        {
            ODataJsonLightAnnotationGroup annotationGroup = new ODataJsonLightAnnotationGroup {
                Annotations = new Dictionary <string, object>(EqualityComparer <string> .Default)
            };

            this.JsonReader.ReadStartObject();
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                this.ProcessProperty(
                    duplicatePropertyNamesChecker,
                    readPropertyAnnotationValue,
                    (propertyParsingResult, propertyName) =>
                {
                    switch (propertyParsingResult)
                    {
                    case PropertyParsingResult.PropertyWithValue:
                        VerifyDataPropertyIsAnnotationName(propertyName, annotationGroup);

                        VerifyAnnotationGroupNameNotYetFound(annotationGroup);
                        annotationGroup.Name = this.JsonReader.ReadStringValue(propertyName);
                        break;

                    case PropertyParsingResult.PropertyWithoutValue:
                        Dictionary <string, object> propertyAnnotations = duplicatePropertyNamesChecker.GetODataPropertyAnnotations(propertyName);
                        if (propertyAnnotations != null)
                        {
                            foreach (KeyValuePair <string, object> propertyAnnotation in propertyAnnotations)
                            {
                                annotationGroup.Annotations.Add(propertyName + JsonLightConstants.ODataPropertyAnnotationSeparatorChar + propertyAnnotation.Key, propertyAnnotation.Value);
                            }
                        }

                        break;

                    case PropertyParsingResult.ODataInstanceAnnotation:
                        annotationGroup.Annotations.Add(propertyName, readInstanceAnnotationValue(propertyName, duplicatePropertyNamesChecker));
                        break;

                    case PropertyParsingResult.CustomInstanceAnnotation:
                        this.JsonReader.SkipValue();
                        break;

                    case PropertyParsingResult.MetadataReferenceProperty:
                        throw CreateExceptionForInvalidAnnotationInsideAnnotationGroup(propertyName, annotationGroup);

                    case PropertyParsingResult.EndOfObject:
                        break;

                    default:
                        throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataJsonLightAnnotationGroupDeserializer_ReadAnnotationGroupDeclaration));
                    }
                });
            }

            VerifyAnnotationGroupNameFound(annotationGroup);
            this.JsonReader.ReadEndObject();
            this.AddAnnotationGroup(annotationGroup);
            return(annotationGroup);
        }
        /// <summary>
        /// Creates an ODataException to throw when a non-annotation property is found inside an annotation group.
        /// </summary>
        /// <param name="propertyName">The name of the property found inside an annotation group.</param>
        /// <param name="annotationGroup">The annotation group it was found in.</param>
        /// <returns>An ODataException with an appropriate message, including the annotation group name if one is available.</returns>
        private static ODataException CreateExceptionForInvalidAnnotationInsideAnnotationGroup(string propertyName, ODataJsonLightAnnotationGroup annotationGroup)
        {
            if (string.IsNullOrEmpty(annotationGroup.Name))
            {
                return(new ODataException(Strings.JsonLightAnnotationGroupDeserializer_InvalidAnnotationFoundInsideAnnotationGroup(propertyName)));
            }

            // Throw a more specific message if we have the annotation group name.
            return(new ODataException(Strings.JsonLightAnnotationGroupDeserializer_InvalidAnnotationFoundInsideNamedAnnotationGroup(annotationGroup.Name, propertyName)));
        }