/// <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); }
/// <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))); }