/// <summary>
        /// Writes all the instance annotations specified in <paramref name="instanceAnnotations"/>.
        /// </summary>
        /// <param name="instanceAnnotations">Collection of instance annotations to write.</param>
        /// <param name="tracker">The tracker to track if instance annotations are written.</param>
        /// <param name="ignoreFilter">Whether to ignore the filter in settings.</param>
        /// <param name="propertyName">The name of the property this instance annotation applies to</param>
        internal void WriteInstanceAnnotations(
            IEnumerable <ODataInstanceAnnotation> instanceAnnotations,
            InstanceAnnotationWriteTracker tracker,
            bool ignoreFilter   = false,
            string propertyName = null)
        {
            Debug.Assert(instanceAnnotations != null, "instanceAnnotations should not be null if we called this");
            Debug.Assert(tracker != null, "tracker should not be null if we called this");

            HashSet <string> instanceAnnotationNames = new HashSet <string>(StringComparer.Ordinal);

            foreach (var annotation in instanceAnnotations)
            {
                if (!instanceAnnotationNames.Add(annotation.Name))
                {
                    throw new ODataException(ODataErrorStrings.JsonLightInstanceAnnotationWriter_DuplicateAnnotationNameInCollection(annotation.Name));
                }

                if (!tracker.IsAnnotationWritten(annotation.Name) &&
                    (!ODataAnnotationNames.IsODataAnnotationName(annotation.Name) || ODataAnnotationNames.IsUnknownODataAnnotationName(annotation.Name)))
                {
                    this.WriteInstanceAnnotation(annotation, ignoreFilter, propertyName);
                    tracker.MarkAnnotationWritten(annotation.Name);
                }
            }
        }
示例#2
0
 public void IsUnknownODataAnnotationNameShouldReturnFalseOnReservedODataAnnotationName()
 {
     foreach (string annotationName in ReservedODataAnnotationNames)
     {
         ODataAnnotationNames.IsUnknownODataAnnotationName(annotationName).Should().BeFalse();
     }
 }
示例#3
0
 public void IsODataAnnotationNameShouldReturnFalseForAnnotationNamesNotUnderODataNamespace()
 {
     ODataAnnotationNames.IsODataAnnotationName("odataa.unknown").Should().BeFalse();
     ODataAnnotationNames.IsODataAnnotationName("oodata.unknown").Should().BeFalse();
     ODataAnnotationNames.IsODataAnnotationName("custom.unknown").Should().BeFalse();
     ODataAnnotationNames.IsODataAnnotationName("OData.unknown").Should().BeFalse();
 }
示例#4
0
 public void ValidateCustomAnnotationNameShouldThrowOnReservedODataAnnotationName()
 {
     foreach (string annotationName in ReservedODataAnnotationNames)
     {
         Action test = () => ODataAnnotationNames.ValidateIsCustomAnnotationName(annotationName);
         test.ShouldThrow <ODataException>().WithMessage(Strings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(annotationName));
     }
 }
示例#5
0
 public void IsUnknownODataAnnotationNameShouldReturnFalseOnCustomAnnotationName()
 {
     ODataAnnotationNames.IsUnknownODataAnnotationName("custom.annotation").Should().BeFalse();
     foreach (string annotationName in ReservedODataAnnotationNames)
     {
         // We match the "odata." namespace case sensitive.
         ODataAnnotationNames.IsUnknownODataAnnotationName(annotationName.ToUpperInvariant()).Should().BeFalse();
     }
 }
示例#6
0
 public void ReservedODataAnnotationNamesHashSetShouldContainAllODataAnnotationNamesSpecialToODataLib()
 {
     Assert.Equal(ReservedODataAnnotationNames.Length, ODataAnnotationNames.KnownODataAnnotationNames.Count);
     foreach (string annotationName in ReservedODataAnnotationNames)
     {
         ODataAnnotationNames.IsODataAnnotationName(annotationName).Should().BeTrue();
         ODataAnnotationNames.KnownODataAnnotationNames.Contains(annotationName).Should().BeTrue();
         ODataAnnotationNames.KnownODataAnnotationNames.Contains(annotationName.ToUpperInvariant()).Should().BeFalse();
     }
 }
示例#7
0
        public void ReservedODataAnnotationNamesHashSetShouldContainAllODataAnnotationNamesSpecialToODataLib()
        {
            Assert.Equal(ReservedODataAnnotationNames.Length, ODataAnnotationNames.KnownODataAnnotationNames.Count);
            foreach (string annotationName in ReservedODataAnnotationNames)
            {
                Assert.True(ODataAnnotationNames.IsODataAnnotationName(annotationName));

                Assert.Contains(annotationName, ODataAnnotationNames.KnownODataAnnotationNames);
                Assert.DoesNotContain(annotationName.ToUpperInvariant(), ODataAnnotationNames.KnownODataAnnotationNames);
            }
        }
        /// <summary>
        /// Reads the json object value from the jsonReader
        /// </summary>
        /// <param name="jsonReader">Json reader to read payload from the wire.</param>
        /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object
        /// (or the second property if the first one was odata.type).</param>
        /// <param name="inputContext">The input context with all the settings.</param>
        /// <param name="recursionDepth">The recursion depth to start with.</param>
        /// <returns>an instance of IDictionary containing the spatial value.</returns>
        private static IDictionary <string, object> ReadObjectValue(IJsonReader jsonReader, bool insideJsonObjectValue, ODataInputContext inputContext, int recursionDepth)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject, "insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject");
            Debug.Assert(
                !insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.Property || jsonReader.NodeType == JsonNodeType.EndObject,
                "!insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.Property || jsonReader.NodeType == JsonNodeType.EndObject");
            Debug.Assert(inputContext != null, "inputContext != null");

            ValidationUtils.IncreaseAndValidateRecursionDepth(ref recursionDepth, inputContext.MessageReaderSettings.MessageQuotas.MaxNestingDepth);

            IDictionary <string, object> jsonValue = new Dictionary <string, object>(StringComparer.Ordinal);

            if (!insideJsonObjectValue)
            {
                // Note that if the insideJsonObjectValue is true we will ignore the odata.type instance annotation
                // which might have been there. This is OK since for spatial we only need the normal properties anyway.
                jsonReader.ReadNext();
            }

            while (jsonReader.NodeType != JsonNodeType.EndObject)
            {
                // read the property name
                string propertyName = jsonReader.ReadPropertyName();

                // read the property value
                object propertyValue = null;
                switch (jsonReader.NodeType)
                {
                case JsonNodeType.PrimitiveValue:
                    propertyValue = jsonReader.ReadPrimitiveValue();
                    break;

                case JsonNodeType.StartArray:
                    propertyValue = ReadArrayValue(jsonReader, inputContext, recursionDepth);
                    break;

                case JsonNodeType.StartObject:
                    propertyValue = ReadObjectValue(jsonReader, /*insideJsonObjectValue*/ false, inputContext, recursionDepth);
                    break;

                default:
                    Debug.Assert(false, "We should never reach here - There should be matching end element");
                    return(null);
                }

                jsonValue.Add(ODataAnnotationNames.RemoveAnnotationPrefix(propertyName), propertyValue);
            }

            jsonReader.ReadEndObject();

            return(jsonValue);
        }
        /// <summary>
        /// Constructs a new <see cref="ODataInstanceAnnotation"/> instance.
        /// </summary>
        /// <param name="annotationName">The name of the instance annotation.</param>
        /// <param name="annotationValue">The value of the instance annotation.</param>
        /// <param name="isCustomAnnotation">If the name is not for built-in OData annotation.</param>
        internal ODataInstanceAnnotation(string annotationName, ODataValue annotationValue, bool isCustomAnnotation)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(annotationName, "annotationName");
            if (!isCustomAnnotation && ODataAnnotationNames.IsODataAnnotationName(annotationName))
            {
                // isCustomAnnotation==true includes '@odata.<unknown name>', which won't cause the below exception.
                throw new ArgumentException(Strings.ODataInstanceAnnotation_ReservedNamesNotAllowed(annotationName, JsonLightConstants.ODataAnnotationNamespacePrefix));
            }

            ValidateName(annotationName);
            ValidateValue(annotationValue);
            this.Name  = annotationName;
            this.Value = annotationValue;
        }
示例#10
0
        /// <summary>
        /// Write instance annotation if not already written.
        /// </summary>
        /// <param name="annotation">The instance annotation to write.</param>
        /// <param name="tracker">The tracker to track if instance annotations are written.</param>
        /// <param name="instanceAnnotationNames">Set used to detect a duplicate annotation.</param>
        /// <param name="ignoreFilter">Whether to ignore the filter in settings.</param>
        /// <param name="propertyName">The name of the property this instance annotation applies to.</param>
        private void WriteAndTrackInstanceAnnotation(
            ODataInstanceAnnotation annotation,
            InstanceAnnotationWriteTracker tracker,
            HashSet <string> instanceAnnotationNames,
            bool ignoreFilter   = false,
            string propertyName = null)
        {
            if (!instanceAnnotationNames.Add(annotation.Name))
            {
                throw new ODataException(ODataErrorStrings.JsonLightInstanceAnnotationWriter_DuplicateAnnotationNameInCollection(annotation.Name));
            }

            if (!tracker.IsAnnotationWritten(annotation.Name) &&
                (!ODataAnnotationNames.IsODataAnnotationName(annotation.Name) || ODataAnnotationNames.IsUnknownODataAnnotationName(annotation.Name)))
            {
                this.WriteInstanceAnnotation(annotation, ignoreFilter, propertyName);
                tracker.MarkAnnotationWritten(annotation.Name);
            }
        }
        /// <summary>
        /// Validates that the given <paramref name="name"/> is a valid instance annotation name.
        /// </summary>
        /// <param name="name">Name to validate.</param>
        internal static void ValidateName(string name)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");

            if (name.IndexOf('.') < 0 || name[0] == '.' || name[name.Length - 1] == '.')
            {
                throw new ArgumentException(Strings.ODataInstanceAnnotation_NeedPeriodInName(name));
            }

            if (ODataAnnotationNames.IsODataAnnotationName(name))
            {
                throw new ArgumentException(Strings.ODataInstanceAnnotation_ReservedNamesNotAllowed(name, JsonLightConstants.ODataAnnotationNamespacePrefix));
            }

            try
            {
                XmlConvert.VerifyNCName(name);
            }
            catch (XmlException e)
            {
                throw new ArgumentException(Strings.ODataInstanceAnnotation_BadTermName(name), e);
            }
        }
示例#12
0
 public void IsODataAnnotationNameShouldReturnTrueForAnnotationNamesUnderODataNamespace()
 {
     ODataAnnotationNames.IsODataAnnotationName("odata.unknown").Should().BeTrue();
 }
示例#13
0
 public void IsODataAnnotationNameShouldReturnFalseForAnnotationNamesNotUnderODataNamespace(string annotationName)
 {
     Assert.False(ODataAnnotationNames.IsODataAnnotationName(annotationName));
 }
示例#14
0
 public void IsUnknownODataAnnotationNameShouldReturnFalseOnPropertyName()
 {
     Assert.False(ODataAnnotationNames.IsUnknownODataAnnotationName("odataPropertyName"));
 }
示例#15
0
 public void IsUnknownODataAnotationNameShouldReturnTrueOnUnknownODataAnnotationName()
 {
     ODataAnnotationNames.IsUnknownODataAnnotationName("odata.unknown").Should().BeTrue();
 }
示例#16
0
 public void IsUnknownODataAnotationNameShouldReturnTrueOnUnknownODataAnnotationName()
 {
     Assert.True(ODataAnnotationNames.IsUnknownODataAnnotationName("odata.unknown"));
 }
        /// <summary>
        /// Writes an instance annotation.
        /// </summary>
        /// <param name="instanceAnnotation">The instance annotation to write.</param>
        internal void WriteInstanceAnnotation(ODataInstanceAnnotation instanceAnnotation)
        {
            DebugUtils.CheckNoExternalCallers();

            string     name  = instanceAnnotation.Name;
            ODataValue value = instanceAnnotation.Value;

            Debug.Assert(!string.IsNullOrEmpty(name), "name should not be null or empty");
            Debug.Assert(!ODataAnnotationNames.IsODataAnnotationName(name), "A reserved name cannot be used as instance annotation key");
            Debug.Assert(value != null, "value should not be null because we use ODataNullValue for null instead");
            Debug.Assert(!(value is ODataStreamReferenceValue), "!(value is ODataStreamReferenceValue) -- ODataInstanceAnnotation and InstanceAnnotationCollection will throw if the value is a stream value.");
            Debug.Assert(this.valueSerializer.Model != null, "this.valueSerializer.Model != null");

            if (this.valueSerializer.Settings.ShouldSkipAnnotation(name))
            {
                return;
            }

            IEdmTypeReference expectedType = MetadataUtils.LookupTypeOfValueTerm(name, this.valueSerializer.Model);

            if (value is ODataNullValue)
            {
                if (expectedType != null && !expectedType.IsNullable)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomPropertyAndValueSerializer_NullValueNotAllowedForInstanceAnnotation(instanceAnnotation.Name, expectedType.ODataFullName()));
                }

                this.JsonWriter.WriteName(name);
                this.valueSerializer.WriteNullValue();
                return;
            }

            // If we didn't find an expected type from looking up the term in the model, treat this value the same way we would for open property values.
            // That is, write the type name (unless its a primitive value with a JSON-native type).  If we did find an expected type, treat the annotation value like a
            // declared property with an expected type. This will still write out the type if the value type is more derived than the declared type, for example.
            bool treatLikeOpenProperty = expectedType == null;

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                this.JsonWriter.WriteName(name);
                this.valueSerializer.WriteComplexValue(complexValue, expectedType, false /*isTopLevel*/, treatLikeOpenProperty, this.valueSerializer.CreateDuplicatePropertyNamesChecker());
                return;
            }

            IEdmTypeReference    typeFromValue   = TypeNameOracle.ResolveAndValidateTypeNameForValue(this.valueSerializer.Model, expectedType, value, treatLikeOpenProperty);
            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                string collectionTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(collectionValue, expectedType, typeFromValue, treatLikeOpenProperty);
                if (collectionTypeNameToWrite != null)
                {
                    ODataJsonLightWriterUtils.WriteODataTypePropertyAnnotation(this.JsonWriter, name, collectionTypeNameToWrite);
                }

                this.JsonWriter.WriteName(name);
                this.valueSerializer.WriteCollectionValue(collectionValue, expectedType, false /*isTopLevelProperty*/, false /*isInUri*/, treatLikeOpenProperty);
                return;
            }

            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            Debug.Assert(primitiveValue != null, "Did we add a new subclass of ODataValue?");

            string primitiveTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(primitiveValue, expectedType, typeFromValue, treatLikeOpenProperty);

            if (primitiveTypeNameToWrite != null)
            {
                ODataJsonLightWriterUtils.WriteODataTypePropertyAnnotation(this.JsonWriter, name, primitiveTypeNameToWrite);
            }

            this.JsonWriter.WriteName(name);
            this.valueSerializer.WritePrimitiveValue(primitiveValue.Value, expectedType);
        }
示例#18
0
 public void IsUnknownODataAnnotationNameShouldReturnFalseOnPropertyName()
 {
     ODataAnnotationNames.IsUnknownODataAnnotationName("odataPropertyName").Should().BeFalse();
 }
示例#19
0
 public void IsODataAnnotationNameShouldReturnTrueForAnnotationNamesUnderODataNamespace()
 {
     Assert.True(ODataAnnotationNames.IsODataAnnotationName("odata.unknown"));
 }