Exemple #1
0
        /// <summary>
        /// Adds an OData annotation to a property.
        /// </summary>
        /// <param name="propertyName">The name of the property to add annotation to. string.empty means the annotation is for the current scope.</param>
        /// <param name="annotationName">The name of the annotation to add.</param>
        /// <param name="annotationValue">The valud of the annotation to add.</param>
        internal void AddODataPropertyAnnotation(string propertyName, string annotationName, object annotationValue)
        {
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");
            Debug.Assert(!string.IsNullOrEmpty(annotationName), "!string.IsNullOrEmpty(annotationName)");
            Debug.Assert(JsonLight.ODataJsonLightReaderUtils.IsODataAnnotationName(annotationName), "annotationName must be an OData annotation.");

            DuplicationRecord           duplicationRecord = this.GetDuplicationRecordToAddPropertyAnnotation(propertyName, annotationName);
            Dictionary <string, object> odataAnnotations  = duplicationRecord.PropertyODataAnnotations;

            if (odataAnnotations == null)
            {
                odataAnnotations = new Dictionary <string, object>(StringComparer.Ordinal);
                duplicationRecord.PropertyODataAnnotations = odataAnnotations;
            }
            else if (odataAnnotations.ContainsKey(annotationName))
            {
                if (ODataJsonLightReaderUtils.IsAnnotationProperty(propertyName))
                {
                    throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicateAnnotationForInstanceAnnotationNotAllowed(annotationName, propertyName));
                }

                throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed(annotationName, propertyName));
            }

            odataAnnotations.Add(annotationName, annotationValue);
        }
        /// <summary>
        /// Sets the properties on a duplication record for a navigation link.
        /// </summary>
        /// <param name="duplicationRecord">The duplication record to modify.</param>
        /// <param name="isExpanded">true if the navigation link is expanded, false otherwise.</param>
        /// <param name="isCollection">true if the navigation link is marked as collection, false if it's marked as singletong or null if we don't know.</param>
        private static void ApplyNavigationLinkToDuplicationRecord(DuplicationRecord duplicationRecord, bool isExpanded, bool?isCollection)
        {
            duplicationRecord.NavigationLinkFound = true;

            // We only take the cardinality of the link for granted if it was expanded or if it is a collection.
            // We can't rely on singleton deferred links to know the cardinality since they can be used for binding even if the actual link is a collection.
            duplicationRecord.NavigationPropertyIsCollection = GetIsCollectionEffectiveValue(isExpanded, isCollection);
        }
 private bool TryGetDuplicationRecord(string propertyName, out DuplicationRecord duplicationRecord)
 {
     if (this.propertyNameCache == null)
     {
         this.propertyNameCache = new Dictionary <string, DuplicationRecord>(EqualityComparer <string> .Default);
         duplicationRecord      = null;
         return(false);
     }
     return(this.propertyNameCache.TryGetValue(propertyName, out duplicationRecord));
 }
Exemple #4
0
        /// <summary>
        /// Tries to get an existing duplication record for the specified <paramref name="propertyName"/>.
        /// </summary>
        /// <param name="propertyName">The property name to look for.</param>
        /// <param name="duplicationRecord">The existing duplication if one was already found.</param>
        /// <returns>true if a duplication record already exists, false otherwise.</returns>
        /// <remarks>This method also initializes the cache if it was not initialized yet.</remarks>
        private bool TryGetDuplicationRecord(string propertyName, out DuplicationRecord duplicationRecord)
        {
            if (this.propertyNameCache == null)
            {
                this.propertyNameCache = new Dictionary <string, DuplicationRecord>(StringComparer.Ordinal);
                duplicationRecord      = null;
                return(false);
            }

            return(this.propertyNameCache.TryGetValue(propertyName, out duplicationRecord));
        }
Exemple #5
0
        /// <summary>
        /// Throw if property is processed already.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="duplicationRecord">DuplicationRecord of the property.</param>
        private static void ThrowIfPropertyIsProcessed(string propertyName, DuplicationRecord duplicationRecord)
        {
            if (object.ReferenceEquals(duplicationRecord.PropertyODataAnnotations, propertyAnnotationsProcessedToken))
            {
                if (ODataJsonLightReaderUtils.IsAnnotationProperty(propertyName) && !ODataJsonLightUtils.IsMetadataReferenceProperty(propertyName))
                {
                    throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicateAnnotationNotAllowed(propertyName));
                }

                throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName));
            }
        }
        /// <summary>
        /// Marks the <paramref name="propertyName"/> property to note that all its annotations were already processed.
        /// </summary>
        /// <param name="propertyName">The property name to mark.</param>
        /// <remarks>
        /// Properties marked like this will fail if there are more annotations found for them in the payload.
        /// </remarks>
        internal void MarkPropertyAsProcessed(string propertyName)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(propertyName != null, "propertyName != null");

            DuplicationRecord duplicationRecord;

            if (!this.TryGetDuplicationRecord(propertyName, out duplicationRecord))
            {
                duplicationRecord = new DuplicationRecord(DuplicationKind.PropertyAnnotationSeen);
                this.propertyNameCache.Add(propertyName, duplicationRecord);
            }

            ThrowIfPropertyIsProcessed(propertyName, duplicationRecord);
            duplicationRecord.PropertyODataAnnotations = propertyAnnotationsProcessedToken;
        }
Exemple #7
0
        /// <summary>
        /// Marks the <paramref name="propertyName"/> property to note that all its annotations were already processed.
        /// </summary>
        /// <param name="propertyName">The property name to mark.</param>
        /// <remarks>
        /// Properties marked like this will fail if there are more annotations found for them in the payload.
        /// </remarks>
        internal void MarkPropertyAsProcessed(string propertyName)
        {
            if (this.disabled)
            {
                return;
            }

            Debug.Assert(propertyName != null, "propertyName != null");

            DuplicationRecord duplicationRecord;

            if (!this.TryGetDuplicationRecord(propertyName, out duplicationRecord))
            {
                duplicationRecord = new DuplicationRecord(DuplicationKind.PropertyAnnotationSeen);
                this.propertyNameCache.Add(propertyName, duplicationRecord);
            }

            ThrowIfPropertyIsProcessed(propertyName, duplicationRecord);
            duplicationRecord.PropertyODataAnnotations = propertyAnnotationsProcessedToken;
        }
 internal void CheckForDuplicatePropertyNames(ODataAssociationLink associationLink)
 {
     DuplicationRecord record;
     string name = associationLink.Name;
     if (!this.TryGetDuplicationRecord(name, out record))
     {
         DuplicationRecord record2 = new DuplicationRecord(DuplicationKind.NavigationProperty) {
             AssociationLinkFound = true
         };
         this.propertyNameCache.Add(name, record2);
     }
     else
     {
         if ((record.DuplicationKind != DuplicationKind.NavigationProperty) || record.AssociationLinkFound)
         {
             throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(name));
         }
         record.AssociationLinkFound = true;
     }
 }
Exemple #9
0
        /// <summary>
        /// Gets a duplication record to use for adding property annotation.
        /// </summary>
        /// <param name="propertyName">The name of the property to get the duplication record for.</param>
        /// <param name="annotationName">The name of the annotation being added (only for error reporting).</param>
        /// <returns>The duplication record to use. This will never be null.</returns>
        private DuplicationRecord GetDuplicationRecordToAddPropertyAnnotation(string propertyName, string annotationName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(!string.IsNullOrEmpty(annotationName), "!string.IsNullOrEmpty(annotationName)");

            DuplicationRecord duplicationRecord;

            if (!this.TryGetDuplicationRecord(propertyName, out duplicationRecord))
            {
                duplicationRecord = new DuplicationRecord(DuplicationKind.PropertyAnnotationSeen);
                this.propertyNameCache.Add(propertyName, duplicationRecord);
            }

            if (object.ReferenceEquals(duplicationRecord.PropertyODataAnnotations, propertyAnnotationsProcessedToken))
            {
                throw new ODataException(Strings.DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty(annotationName, propertyName));
            }

            Debug.Assert(duplicationRecord != null, "duplicationRecord != null");
            return(duplicationRecord);
        }
Exemple #10
0
        /// <summary>
        /// Adds a custom annotation to a property.
        /// </summary>
        /// <param name="propertyName">The name of the property to add annotation to. string.empty means the annotation is for the current scope.</param>
        /// <param name="annotationName">The name of the annotation to add.</param>
        internal void AddCustomPropertyAnnotation(string propertyName, string annotationName)
        {
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");
            Debug.Assert(!string.IsNullOrEmpty(annotationName), "!string.IsNullOrEmpty(annotationName)");
            Debug.Assert(!JsonLight.ODataJsonLightReaderUtils.IsODataAnnotationName(annotationName), "annotationName must not be an OData annotation.");

            DuplicationRecord duplicationRecord = this.GetDuplicationRecordToAddPropertyAnnotation(propertyName, annotationName);
            HashSet <string>  customAnnotations = duplicationRecord.PropertyCustomAnnotations;

            if (customAnnotations == null)
            {
                customAnnotations = new HashSet <string>(StringComparer.Ordinal);
                duplicationRecord.PropertyCustomAnnotations = customAnnotations;
            }
            else if (customAnnotations.Contains(annotationName))
            {
                throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed(annotationName, propertyName));
            }

            customAnnotations.Add(annotationName);
        }
        internal void CheckForDuplicatePropertyNames(ODataAssociationLink associationLink)
        {
            DuplicationRecord record;
            string            name = associationLink.Name;

            if (!this.TryGetDuplicationRecord(name, out record))
            {
                DuplicationRecord record2 = new DuplicationRecord(DuplicationKind.NavigationProperty)
                {
                    AssociationLinkFound = true
                };
                this.propertyNameCache.Add(name, record2);
            }
            else
            {
                if ((record.DuplicationKind != DuplicationKind.NavigationProperty) || record.AssociationLinkFound)
                {
                    throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(name));
                }
                record.AssociationLinkFound = true;
            }
        }
        internal void CheckForDuplicatePropertyNames(ODataNavigationLink navigationLink, bool isExpanded, bool?isCollection)
        {
            DuplicationRecord record;
            string            name = navigationLink.Name;

            if (!this.TryGetDuplicationRecord(name, out record))
            {
                DuplicationRecord duplicationRecord = new DuplicationRecord(DuplicationKind.NavigationProperty);
                ApplyNavigationLinkToDuplicationRecord(duplicationRecord, isExpanded, isCollection);
                this.propertyNameCache.Add(name, duplicationRecord);
            }
            else
            {
                this.CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(name, record);
                if (((record.DuplicationKind == DuplicationKind.NavigationProperty) && record.AssociationLinkFound) && !record.NavigationLinkFound)
                {
                    ApplyNavigationLinkToDuplicationRecord(record, isExpanded, isCollection);
                }
                else if (this.allowDuplicateProperties)
                {
                    record.DuplicationKind = DuplicationKind.NavigationProperty;
                    ApplyNavigationLinkToDuplicationRecord(record, isExpanded, isCollection);
                }
                else
                {
                    bool?isCollectionEffectiveValue = GetIsCollectionEffectiveValue(isExpanded, isCollection);
                    if ((isCollectionEffectiveValue == false) || (record.NavigationPropertyIsCollection == false))
                    {
                        throw new ODataException(Strings.DuplicatePropertyNamesChecker_MultipleLinksForSingleton(name));
                    }
                    if (isCollectionEffectiveValue.HasValue)
                    {
                        record.NavigationPropertyIsCollection = isCollectionEffectiveValue;
                    }
                }
            }
        }
 internal void CheckForDuplicatePropertyNames(ODataNavigationLink navigationLink, bool isExpanded, bool? isCollection)
 {
     DuplicationRecord record;
     string name = navigationLink.Name;
     if (!this.TryGetDuplicationRecord(name, out record))
     {
         DuplicationRecord duplicationRecord = new DuplicationRecord(DuplicationKind.NavigationProperty);
         ApplyNavigationLinkToDuplicationRecord(duplicationRecord, isExpanded, isCollection);
         this.propertyNameCache.Add(name, duplicationRecord);
     }
     else
     {
         this.CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(name, record);
         if (((record.DuplicationKind == DuplicationKind.NavigationProperty) && record.AssociationLinkFound) && !record.NavigationLinkFound)
         {
             ApplyNavigationLinkToDuplicationRecord(record, isExpanded, isCollection);
         }
         else if (this.allowDuplicateProperties)
         {
             record.DuplicationKind = DuplicationKind.NavigationProperty;
             ApplyNavigationLinkToDuplicationRecord(record, isExpanded, isCollection);
         }
         else
         {
             bool? isCollectionEffectiveValue = GetIsCollectionEffectiveValue(isExpanded, isCollection);
             if ((isCollectionEffectiveValue == false) || (record.NavigationPropertyIsCollection == false))
             {
                 throw new ODataException(Strings.DuplicatePropertyNamesChecker_MultipleLinksForSingleton(name));
             }
             if (isCollectionEffectiveValue.HasValue)
             {
                 record.NavigationPropertyIsCollection = isCollectionEffectiveValue;
             }
         }
     }
 }
 private static void ApplyNavigationLinkToDuplicationRecord(DuplicationRecord duplicationRecord, bool isExpanded, bool? isCollection)
 {
     duplicationRecord.NavigationLinkFound = true;
     duplicationRecord.NavigationPropertyIsCollection = GetIsCollectionEffectiveValue(isExpanded, isCollection);
 }
        /// <summary>
        /// Tries to get an existing duplication record for the specified <paramref name="propertyName"/>.
        /// </summary>
        /// <param name="propertyName">The property name to look for.</param>
        /// <param name="duplicationRecord">The existing duplication if one was already found.</param>
        /// <returns>true if a duplication record already exists, false otherwise.</returns>
        /// <remarks>This method also initializes the cache if it was not initialized yet.</remarks>
        private bool TryGetDuplicationRecord(string propertyName, out DuplicationRecord duplicationRecord)
        {
            if (this.propertyNameCache == null)
            {
                this.propertyNameCache = new Dictionary<string, DuplicationRecord>(EqualityComparer<string>.Default);
                duplicationRecord = null;
                return false;
            }

            return this.propertyNameCache.TryGetValue(propertyName, out duplicationRecord);
        }
        /// <summary>
        /// Check the <paramref name="navigationLink"/> for duplicate property names in an entry or complex value.
        /// If not explicitly allowed throw when duplicate properties are detected.
        /// If duplicate properties are allowed see the comment on ODataWriterBehavior.AllowDuplicatePropertyNames 
        /// or ODataReaderBehavior.AllowDuplicatePropertyNames for further details.
        /// </summary>
        /// <param name="navigationLink">The navigation link to be checked.</param>
        /// <param name="isExpanded">true if the link is expanded, false otherwise.</param>
        /// <param name="isCollection">true if the navigation link is a collection, false if it's a singleton or null if we don't know.</param>
        /// <returns>The association link uri with the same name if there already was one.</returns>
        internal Uri CheckForDuplicatePropertyNames(ODataNavigationLink navigationLink, bool isExpanded, bool? isCollection)
        {
            if (this.disabled)
            {
                return null;
            }
#if DEBUG
            this.startNavigationLinkName = null;
#endif

            string propertyName = navigationLink.Name;
            DuplicationRecord existingDuplicationRecord;
            if (!this.TryGetDuplicationRecord(propertyName, out existingDuplicationRecord))
            {
                DuplicationRecord duplicationRecord = new DuplicationRecord(DuplicationKind.NavigationProperty);
                ApplyNavigationLinkToDuplicationRecord(duplicationRecord, navigationLink, isExpanded, isCollection);
                this.propertyNameCache.Add(propertyName, duplicationRecord);
                return null;
            }
            else
            {
                // First check for duplication without expansion knowledge.
                this.CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(propertyName, existingDuplicationRecord);

                if (existingDuplicationRecord.DuplicationKind == DuplicationKind.PropertyAnnotationSeen ||
                    (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty &&
                    existingDuplicationRecord.AssociationLinkName != null &&
                    existingDuplicationRecord.NavigationLink == null))
                {
                    // If the existing one is just an association link, update it to include the navigation link portion as well
                    ApplyNavigationLinkToDuplicationRecord(existingDuplicationRecord, navigationLink, isExpanded, isCollection);
                }
                else if (this.allowDuplicateProperties)
                {
                    Debug.Assert(
                        (existingDuplicationRecord.DuplicationKind == DuplicationKind.PotentiallyAllowed || existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty),
                        "We should have already taken care of prohibit duplication.");

                    // If the configuration explicitly allows duplication, then just turn the existing property into a nav link with all the information we have
                    existingDuplicationRecord.DuplicationKind = DuplicationKind.NavigationProperty;
                    ApplyNavigationLinkToDuplicationRecord(existingDuplicationRecord, navigationLink, isExpanded, isCollection);
                }
                else
                {
                    // We've found two navigation links in a request
                    Debug.Assert(
                        existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty && existingDuplicationRecord.NavigationLink != null && !this.isResponse,
                        "We can only get here if we've found two navigation links in a request.");

                    bool? isCollectionEffectiveValue = GetIsCollectionEffectiveValue(isExpanded, isCollection);

                    // If one of them is a definitive singleton, then we fail.
                    if (isCollectionEffectiveValue == false || existingDuplicationRecord.NavigationPropertyIsCollection == false)
                    {
                        // This is the case where an expanded singleton is followed by a deferred link for example.
                        // Once we know for sure that the nav. prop. is a singleton we can't allow more than one link for it.
                        throw new ODataException(Strings.DuplicatePropertyNamesChecker_MultipleLinksForSingleton(propertyName));
                    }

                    // Otherwise allow it, but update the link with the new information
                    if (isCollectionEffectiveValue.HasValue)
                    {
                        existingDuplicationRecord.NavigationPropertyIsCollection = isCollectionEffectiveValue;
                    }
                }

                return existingDuplicationRecord.AssociationLinkUrl;
            }
        }
Exemple #17
0
        /// <summary>
        /// Check the <paramref name="navigationLink"/> for duplicate property names in an entry or complex value.
        /// If not explicitly allowed throw when duplicate properties are detected.
        /// If duplicate properties are allowed see the comment on ODataWriterBehavior.AllowDuplicatePropertyNames
        /// or ODataReaderBehavior.AllowDuplicatePropertyNames for further details.
        /// </summary>
        /// <param name="navigationLink">The navigation link to be checked.</param>
        /// <param name="isExpanded">true if the link is expanded, false otherwise.</param>
        /// <param name="isCollection">true if the navigation link is a collection, false if it's a singleton or null if we don't know.</param>
        /// <returns>The association link uri with the same name if there already was one.</returns>
        internal Uri CheckForDuplicatePropertyNames(ODataNavigationLink navigationLink, bool isExpanded, bool?isCollection)
        {
            if (this.disabled)
            {
                return(null);
            }
#if DEBUG
            this.startNavigationLinkName = null;
#endif

            string            propertyName = navigationLink.Name;
            DuplicationRecord existingDuplicationRecord;
            if (!this.TryGetDuplicationRecord(propertyName, out existingDuplicationRecord))
            {
                DuplicationRecord duplicationRecord = new DuplicationRecord(DuplicationKind.NavigationProperty);
                ApplyNavigationLinkToDuplicationRecord(duplicationRecord, navigationLink, isExpanded, isCollection);
                this.propertyNameCache.Add(propertyName, duplicationRecord);
                return(null);
            }
            else
            {
                // First check for duplication without expansion knowledge.
                this.CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(propertyName, existingDuplicationRecord);

                if (existingDuplicationRecord.DuplicationKind == DuplicationKind.PropertyAnnotationSeen ||
                    (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty &&
                     existingDuplicationRecord.AssociationLinkName != null &&
                     existingDuplicationRecord.NavigationLink == null))
                {
                    // If the existing one is just an association link, update it to include the navigation link portion as well
                    ApplyNavigationLinkToDuplicationRecord(existingDuplicationRecord, navigationLink, isExpanded, isCollection);
                }
                else if (this.allowDuplicateProperties)
                {
                    Debug.Assert(
                        (existingDuplicationRecord.DuplicationKind == DuplicationKind.PotentiallyAllowed || existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty),
                        "We should have already taken care of prohibit duplication.");

                    // If the configuration explicitly allows duplication, then just turn the existing property into a nav link with all the information we have
                    existingDuplicationRecord.DuplicationKind = DuplicationKind.NavigationProperty;
                    ApplyNavigationLinkToDuplicationRecord(existingDuplicationRecord, navigationLink, isExpanded, isCollection);
                }
                else
                {
                    // We've found two navigation links in a request
                    Debug.Assert(
                        existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty && existingDuplicationRecord.NavigationLink != null && !this.isResponse,
                        "We can only get here if we've found two navigation links in a request.");

                    bool?isCollectionEffectiveValue = GetIsCollectionEffectiveValue(isExpanded, isCollection);

                    // If one of them is a definitive singleton, then we fail.
                    if (isCollectionEffectiveValue == false || existingDuplicationRecord.NavigationPropertyIsCollection == false)
                    {
                        // This is the case where an expanded singleton is followed by a deferred link for example.
                        // Once we know for sure that the nav. prop. is a singleton we can't allow more than one link for it.
                        throw new ODataException(Strings.DuplicatePropertyNamesChecker_MultipleLinksForSingleton(propertyName));
                    }

                    // Otherwise allow it, but update the link with the new information
                    if (isCollectionEffectiveValue.HasValue)
                    {
                        existingDuplicationRecord.NavigationPropertyIsCollection = isCollectionEffectiveValue;
                    }
                }

                return(existingDuplicationRecord.AssociationLinkUrl);
            }
        }
        /// <summary>
        /// Marks the <paramref name="propertyName"/> property to note that all its annotations were already processed.
        /// </summary>
        /// <param name="propertyName">The property name to mark.</param>
        /// <remarks>
        /// Properties marked like this will fail if there are more annotations found for them in the payload.
        /// </remarks>
        internal void MarkPropertyAsProcessed(string propertyName)
        {
            if (this.disabled)
            {
                return;
            }

            Debug.Assert(propertyName != null, "propertyName != null");

            DuplicationRecord duplicationRecord;
            if (!this.TryGetDuplicationRecord(propertyName, out duplicationRecord))
            {
                duplicationRecord = new DuplicationRecord(DuplicationKind.PropertyAnnotationSeen);
                this.propertyNameCache.Add(propertyName, duplicationRecord);
            }

            ThrowIfPropertyIsProcessed(propertyName, duplicationRecord);
            duplicationRecord.PropertyODataAnnotations = propertyAnnotationsProcessedToken;
        }
        /// <summary>
        /// Tries to get an existing duplication record for the specified <paramref name="propertyName"/>.
        /// </summary>
        /// <param name="propertyName">The property name to look for.</param>
        /// <param name="duplicationRecord">The existing duplication if one was already found.</param>
        /// <returns>true if a duplication record already exists, false otherwise.</returns>
        /// <remarks>This method also initializes the cache if it was not initialized yet.</remarks>
        private bool TryGetDuplicationRecord(string propertyName, out DuplicationRecord duplicationRecord)
        {
            if (this.propertyNameCache == null)
            {
                this.propertyNameCache = new Dictionary<string, DuplicationRecord>(StringComparer.Ordinal);
                duplicationRecord = null;
                return false;
            }

            return this.propertyNameCache.TryGetValue(propertyName, out duplicationRecord);
        }
 private static void ApplyNavigationLinkToDuplicationRecord(DuplicationRecord duplicationRecord, bool isExpanded, bool?isCollection)
 {
     duplicationRecord.NavigationLinkFound            = true;
     duplicationRecord.NavigationPropertyIsCollection = GetIsCollectionEffectiveValue(isExpanded, isCollection);
 }
        /// <summary>
        /// Throw if property is processed already.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="duplicationRecord">DuplicationRecord of the property.</param>
        private static void ThrowIfPropertyIsProcessed(string propertyName, DuplicationRecord duplicationRecord)
        {
            if (object.ReferenceEquals(duplicationRecord.PropertyODataAnnotations, propertyAnnotationsProcessedToken))
            {
                if (ODataJsonLightReaderUtils.IsAnnotationProperty(propertyName) && !ODataJsonLightUtils.IsMetadataReferenceProperty(propertyName))
                {
                    throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicateAnnotationNotAllowed(propertyName));
                }

                throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName));
            }
        }
 private void CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(string propertyName, DuplicationRecord existingDuplicationRecord)
 {
     if ((((existingDuplicationRecord.DuplicationKind != DuplicationKind.NavigationProperty) || !existingDuplicationRecord.AssociationLinkFound) || existingDuplicationRecord.NavigationLinkFound) && (((existingDuplicationRecord.DuplicationKind == DuplicationKind.Prohibited) || ((existingDuplicationRecord.DuplicationKind == DuplicationKind.PotentiallyAllowed) && !this.allowDuplicateProperties)) || (((existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty) && this.isResponse) && !this.allowDuplicateProperties)))
     {
         throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName));
     }
 }
 private void CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(string propertyName, DuplicationRecord existingDuplicationRecord)
 {
     if ((((existingDuplicationRecord.DuplicationKind != DuplicationKind.NavigationProperty) || !existingDuplicationRecord.AssociationLinkFound) || existingDuplicationRecord.NavigationLinkFound) && (((existingDuplicationRecord.DuplicationKind == DuplicationKind.Prohibited) || ((existingDuplicationRecord.DuplicationKind == DuplicationKind.PotentiallyAllowed) && !this.allowDuplicateProperties)) || (((existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty) && this.isResponse) && !this.allowDuplicateProperties)))
     {
         throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName));
     }
 }
 /// <summary>
 /// Checks for duplication of a navigation link against an existing duplication record.
 /// </summary>
 /// <param name="propertyName">The name of the navigation link.</param>
 /// <param name="existingDuplicationRecord">The existing duplication record.</param>
 /// <remarks>This only performs checks possible without the knowledge of whether the link was expanded or not.</remarks>
 private void CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(string propertyName, DuplicationRecord existingDuplicationRecord)
 {
     if (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty &&
         existingDuplicationRecord.AssociationLinkUrl != null &&
         existingDuplicationRecord.NavigationLink == null)
     {
         // Existing one is just an association link, so the new one is a navigation link portion which is OK always.
     }
     else if (existingDuplicationRecord.DuplicationKind == DuplicationKind.Prohibited ||
         (existingDuplicationRecord.DuplicationKind == DuplicationKind.PotentiallyAllowed && !this.allowDuplicateProperties) ||
         (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty && this.isResponse && !this.allowDuplicateProperties))
     {
         // If the existing one doesn't allow duplication at all,
         // or it's simple property which does allow duplication, but the configuration does not allow it,
         // or it's a duplicate navigation property in a response,
         // fail.
         throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName));
     }
 }
Exemple #25
0
 /// <summary>
 /// Checks for duplication of a navigation link against an existing duplication record.
 /// </summary>
 /// <param name="propertyName">The name of the navigation link.</param>
 /// <param name="existingDuplicationRecord">The existing duplication record.</param>
 /// <remarks>This only performs checks possible without the knowledge of whether the link was expanded or not.</remarks>
 private void CheckNavigationLinkDuplicateNameForExistingDuplicationRecord(string propertyName, DuplicationRecord existingDuplicationRecord)
 {
     if (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty &&
         existingDuplicationRecord.AssociationLinkUrl != null &&
         existingDuplicationRecord.NavigationLink == null)
     {
         // Existing one is just an association link, so the new one is a navigation link portion which is OK always.
     }
     else if (existingDuplicationRecord.DuplicationKind == DuplicationKind.Prohibited ||
              (existingDuplicationRecord.DuplicationKind == DuplicationKind.PotentiallyAllowed && !this.allowDuplicateProperties) ||
              (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty && this.isResponse && !this.allowDuplicateProperties))
     {
         // If the existing one doesn't allow duplication at all,
         // or it's simple property which does allow duplication, but the configuration does not allow it,
         // or it's a duplicate navigation property in a response,
         // fail.
         throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName));
     }
 }
        /// <summary>
        /// Gets a duplication record to use for adding property annotation.
        /// </summary>
        /// <param name="propertyName">The name of the property to get the duplication record for.</param>
        /// <param name="annotationName">The name of the annotation being added (only for error reporting).</param>
        /// <returns>The duplication record to use. This will never be null.</returns>
        private DuplicationRecord GetDuplicationRecordToAddPropertyAnnotation(string propertyName, string annotationName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(!string.IsNullOrEmpty(annotationName), "!string.IsNullOrEmpty(annotationName)");

            DuplicationRecord duplicationRecord;
            if (!this.TryGetDuplicationRecord(propertyName, out duplicationRecord))
            {
                duplicationRecord = new DuplicationRecord(DuplicationKind.PropertyAnnotationSeen);
                this.propertyNameCache.Add(propertyName, duplicationRecord);
            }

            if (object.ReferenceEquals(duplicationRecord.PropertyODataAnnotations, propertyAnnotationsProcessedToken))
            {
                throw new ODataException(Strings.DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty(annotationName, propertyName));
            }

            Debug.Assert(duplicationRecord != null, "duplicationRecord != null");
            return duplicationRecord;
        }
        /// <summary>
        /// Sets the properties on a duplication record for a navigation link.
        /// </summary>
        /// <param name="duplicationRecord">The duplication record to modify.</param>
        /// <param name="navigationLink">The navigation link found for this property.</param>
        /// <param name="isExpanded">true if the navigation link is expanded, false otherwise.</param>
        /// <param name="isCollection">true if the navigation link is marked as collection, false if it's marked as singletong or null if we don't know.</param>
        private static void ApplyNavigationLinkToDuplicationRecord(DuplicationRecord duplicationRecord, ODataNavigationLink navigationLink, bool isExpanded, bool? isCollection)
        {
            duplicationRecord.DuplicationKind = DuplicationKind.NavigationProperty;
            duplicationRecord.NavigationLink = navigationLink;

            // We only take the cardinality of the link for granted if it was expanded or if it is a collection.
            // We can't rely on singleton deferred links to know the cardinality since they can be used for binding even if the actual link is a collection.
            duplicationRecord.NavigationPropertyIsCollection = GetIsCollectionEffectiveValue(isExpanded, isCollection);
        }