/// <summary>
        /// Parses JSON object property starting with the current position of the JSON reader.
        /// </summary>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use, it will also store the property annotations found.</param>
        /// <param name="readPropertyAnnotationValue">Function called to read property annotation value.</param>
        /// <param name="handleProperty">Function callback to handle to resule of parse property.</param>
        internal void ProcessProperty(
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            Func <string, object> readPropertyAnnotationValue,
            Action <PropertyParsingResult, string> handleProperty)
        {
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");
            Debug.Assert(readPropertyAnnotationValue != null, "readPropertyAnnotationValue != null");
            Debug.Assert(handleProperty != null, "handleProperty != null");
            this.AssertJsonCondition(JsonNodeType.Property);

            string propertyName;
            PropertyParsingResult propertyParsingResult = this.ParseProperty(duplicatePropertyNamesChecker, readPropertyAnnotationValue, out propertyName);

            while (propertyParsingResult == PropertyParsingResult.CustomInstanceAnnotation && this.ShouldSkipCustomInstanceAnnotation(propertyName))
            {
                // Make sure there's no duplicated instance annotation name even though we are skipping over it.
                duplicatePropertyNamesChecker.MarkPropertyAsProcessed(propertyName);

                // Skip over the instance annotation value and don't report it to the OM.
                this.JsonReader.SkipValue();

                propertyParsingResult = this.ParseProperty(duplicatePropertyNamesChecker, readPropertyAnnotationValue, out propertyName);
            }

            handleProperty(propertyParsingResult, propertyName);
            if (propertyParsingResult != PropertyParsingResult.EndOfObject)
            {
                duplicatePropertyNamesChecker.MarkPropertyAsProcessed(propertyName);
            }
        }
 public void DuplicateInstanceCustomAnnotationShouldFail()
 {
     DuplicatePropertyNamesChecker duplicateChecker = new DuplicatePropertyNamesChecker(false, true);
     Action action = () => duplicateChecker.MarkPropertyAsProcessed("custom.name");
     action.ShouldNotThrow();
     action.ShouldThrow<ODataException>().WithMessage(ErrorStrings.DuplicatePropertyNamesChecker_DuplicateAnnotationNotAllowed("custom.name"));
 }
示例#3
0
        public void DuplicateInstanceCustomAnnotationShouldFail()
        {
            DuplicatePropertyNamesChecker duplicateChecker = new DuplicatePropertyNamesChecker(false, true);
            Action action = () => duplicateChecker.MarkPropertyAsProcessed("custom.name");

            action.ShouldNotThrow();
            action.ShouldThrow <ODataException>().WithMessage(ErrorStrings.DuplicatePropertyNamesChecker_DuplicateAnnotationNotAllowed("custom.name"));
        }
示例#4
0
        public void MarkPropertyAsProcessedWithNoPropertyShouldWork()
        {
            DuplicatePropertyNamesChecker duplicateChecker = new DuplicatePropertyNamesChecker(false, true);

            duplicateChecker.MarkPropertyAsProcessed("property");
            Action odataAction = () => duplicateChecker.AddODataPropertyAnnotation("property", JsonLightConstants.ODataAnnotationNamespacePrefix + "name", null);

            odataAction.ShouldThrow <ODataException>().WithMessage(ErrorStrings.DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty(JsonLightConstants.ODataAnnotationNamespacePrefix + "name", "property"));
            Action customAction = () => duplicateChecker.AddCustomPropertyAnnotation("property", "custom.name");

            customAction.ShouldThrow <ODataException>().WithMessage(ErrorStrings.DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty("custom.name", "property"));
        }
        /// <summary>
        /// Reads the odata.context annotation.
        /// </summary>
        /// <param name="payloadKind">The payload kind for which to read the context URI.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker.</param>
        /// <param name="failOnMissingContextUriAnnotation">true if the method should fail if the context URI annotation is missing, false if that can be ignored.</param>
        /// <returns>The value of the context URI annotation.</returns>
        internal string ReadContextUriAnnotation(
            ODataPayloadKind payloadKind,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            bool failOnMissingContextUriAnnotation)
        {
            if (this.JsonReader.NodeType != JsonNodeType.Property)
            {
                if (!failOnMissingContextUriAnnotation || payloadKind == ODataPayloadKind.Unsupported)
                {
                    // Do not fail during payload kind detection
                    return(null);
                }

                throw new ODataException(OData.Core.Strings.ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty);
            }

            // Must make sure the input odata.context has a '@' prefix
            string propertyName = this.JsonReader.GetPropertyName();

            if (string.CompareOrdinal(JsonLightConstants.ODataPropertyAnnotationSeparatorChar + ODataAnnotationNames.ODataContext, propertyName) != 0 &&
                !this.CompareSimplifiedODataAnnotation(JsonLightConstants.SimplifiedODataContextPropertyName, propertyName))
            {
                if (!failOnMissingContextUriAnnotation || payloadKind == ODataPayloadKind.Unsupported)
                {
                    // Do not fail during payload kind detection
                    return(null);
                }

                throw new ODataException(OData.Core.Strings.ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty);
            }

            if (duplicatePropertyNamesChecker != null)
            {
                duplicatePropertyNamesChecker.MarkPropertyAsProcessed(propertyName);
            }

            // Read over the property name
            this.JsonReader.ReadNext();
            return(this.JsonReader.ReadStringValue());
        }
示例#6
0
        /// <summary>
        /// Reads the odata.metadata annotation.
        /// </summary>
        /// <param name="payloadKind">The payload kind for which to read the metadata URI.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker.</param>
        /// <param name="failOnMissingMetadataUriAnnotation">true if the method should fail if the metadata URI annotation is missing, false if that can be ignored.</param>
        /// <returns>The value of the metadata URI annotation.</returns>
        private string ReadMetadataUriAnnotation(
            ODataPayloadKind payloadKind,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            bool failOnMissingMetadataUriAnnotation)
        {
            if (this.JsonReader.NodeType != JsonNodeType.Property)
            {
                if (!failOnMissingMetadataUriAnnotation || payloadKind == ODataPayloadKind.Unsupported)
                {
                    // Do not fail during payload kind detection
                    return(null);
                }

                throw new ODataException(OData.Strings.ODataJsonLightDeserializer_MetadataLinkNotFoundAsFirstProperty);
            }

            string propertyName = this.JsonReader.GetPropertyName();

            if (string.CompareOrdinal(ODataAnnotationNames.ODataMetadata, propertyName) != 0)
            {
                if (!failOnMissingMetadataUriAnnotation || payloadKind == ODataPayloadKind.Unsupported)
                {
                    // Do not fail during payload kind detection
                    return(null);
                }

                throw new ODataException(OData.Strings.ODataJsonLightDeserializer_MetadataLinkNotFoundAsFirstProperty);
            }

            if (duplicatePropertyNamesChecker != null)
            {
                duplicatePropertyNamesChecker.MarkPropertyAsProcessed(propertyName);
            }

            // Read over the property name
            this.JsonReader.ReadNext();
            return(this.JsonReader.ReadStringValue());
        }
        /// <summary>
        /// Detects whether we are currently reading a complex property or not. This can be determined from metadata (if we have it)
        /// or from the presence of the odata.type instance annotation in the payload.
        /// </summary>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker in use for the entry content.</param>
        /// <param name="expectedPropertyTypeReference">The expected type reference of the property to read.</param>
        /// <param name="payloadTypeName">The type name of the complex value if found in the payload; otherwise null.</param>
        /// <returns>true if we are reading a complex property; otherwise false.</returns>
        /// <remarks>
        /// This method does not move the reader.
        /// </remarks>
        private bool ReadingComplexProperty(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, IEdmTypeReference expectedPropertyTypeReference, out string payloadTypeName)
        {
            payloadTypeName = null;
            bool readingComplexProperty = false;

            // First try to use the metadata if is available
            if (expectedPropertyTypeReference != null)
            {
                readingComplexProperty = expectedPropertyTypeReference.IsComplex();
            }

            // Then check whether the first property in the JSON object is the 'odata.type'
            // annotation; if we don't have an expected property type reference, the 'odata.type'
            // annotation has to exist for complex properties. (This can happen for top-level open 
            // properties).
            if (this.JsonReader.NodeType == JsonNodeType.Property && this.TryReadODataTypeAnnotation(out payloadTypeName))
            {
                // Register the odata.type annotation we just found with the duplicate property names checker.
                duplicatePropertyNamesChecker.MarkPropertyAsProcessed(ODataAnnotationNames.ODataType);

                IEdmType expectedPropertyType = null;
                if (expectedPropertyTypeReference != null)
                {
                    expectedPropertyType = expectedPropertyTypeReference.Definition;
                }

                EdmTypeKind typeKind = EdmTypeKind.None;
                IEdmType actualWirePropertyTypeReference = MetadataUtils.ResolveTypeNameForRead(
                    this.Model,
                    expectedPropertyType,
                    payloadTypeName,
                    this.MessageReaderSettings.ReaderBehavior,
                    out typeKind);

                if (actualWirePropertyTypeReference != null)
                {
                    readingComplexProperty = actualWirePropertyTypeReference.IsODataComplexTypeKind();
                }
            }

            return readingComplexProperty;
        }
        /// <summary>
        /// Reads the payload type name from a JSON object (if it exists).
        /// </summary>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to track the detected 'odata.type' annotation (if any).</param>
        /// <param name="insideComplexValue">true if we are reading a complex value and the reader is already positioned inside the complex value; otherwise false.</param>
        /// <param name="payloadTypeName">The value of the odata.type annotation or null if no such annotation exists.</param>
        /// <returns>true if a type name was read from the payload; otherwise false.</returns>
        /// <remarks>
        /// Precondition:   StartObject     the start of a JSON object
        /// Postcondition:  Property        the first property of the object if no 'odata.type' annotation exists as first property
        ///                                 or the first property after the 'odata.type' annotation.
        ///                 EndObject       for an empty JSON object or an object with only the 'odata.type' annotation
        /// </remarks>
        private bool TryReadPayloadTypeFromObject(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool insideComplexValue, out string payloadTypeName)
        {
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");
            Debug.Assert(
                (this.JsonReader.NodeType == JsonNodeType.StartObject && !insideComplexValue) ||
                ((this.JsonReader.NodeType == JsonNodeType.Property || this.JsonReader.NodeType == JsonNodeType.EndObject) && insideComplexValue),
                "Pre-Condition: JsonNodeType.StartObject when not inside complex value; JsonNodeType.Property or JsonNodeType.EndObject otherwise.");
            bool readTypeName = false;
            payloadTypeName = null;

            // If not already positioned inside the JSON object, read over the object start
            if (!insideComplexValue)
            {
                this.JsonReader.ReadStartObject();
            }

            if (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                readTypeName = this.TryReadODataTypeAnnotation(out payloadTypeName);
                if (readTypeName)
                {
                    // Register the odata.type annotation we just found with the duplicate property names checker.
                    duplicatePropertyNamesChecker.MarkPropertyAsProcessed(ODataAnnotationNames.ODataType);
                }
            }

            this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject);
            return readTypeName;
        }
 public void MarkPropertyAsProcessedWithNoPropertyShouldWork()
 {
     DuplicatePropertyNamesChecker duplicateChecker = new DuplicatePropertyNamesChecker(false, true);
     duplicateChecker.MarkPropertyAsProcessed("property");
     Action odataAction = () => duplicateChecker.AddODataPropertyAnnotation("property", JsonLightConstants.ODataAnnotationNamespacePrefix + "name", null);
     odataAction.ShouldThrow<ODataException>().WithMessage(ErrorStrings.DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty(JsonLightConstants.ODataAnnotationNamespacePrefix + "name", "property"));
     Action customAction = () => duplicateChecker.AddCustomPropertyAnnotation("property", "custom.name");
     customAction.ShouldThrow<ODataException>().WithMessage(ErrorStrings.DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty("custom.name", "property"));
 }