/// <summary> /// Check the <paramref name="associationLink"/> 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="associationLink">The association link to be checked.</param> internal void CheckForDuplicatePropertyNames(ODataAssociationLink associationLink) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(associationLink != null, "associationLink != null"); #if DEBUG Debug.Assert(this.startNavigationLinkName == null, "CheckForDuplicatePropertyNamesOnNavigationLinkStart was followed by a CheckForDuplicatePropertyNames(ODataProperty)."); #endif string propertyName = associationLink.Name; DuplicationRecord existingDuplicationRecord; if (!this.TryGetDuplicationRecord(propertyName, out existingDuplicationRecord)) { this.propertyNameCache.Add( propertyName, new DuplicationRecord(DuplicationKind.NavigationProperty) { AssociationLinkFound = true }); } else { if (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty && !existingDuplicationRecord.AssociationLinkFound) { // The only valid case for a duplication with association link is if the existing record is for a navigation property // which doesn't have its association link yet. // In this case just mark the navigation property as having found its association link. existingDuplicationRecord.AssociationLinkFound = true; } else { // In all other cases fail. 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> /// 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)); } }
internal void CheckForDuplicatePropertyNames(ODataProperty property) { DuplicationRecord record; string name = property.Name; DuplicationKind duplicationKind = GetDuplicationKind(property); if (!this.TryGetDuplicationRecord(name, out record)) { this.propertyNameCache.Add(name, new DuplicationRecord(duplicationKind)); } else if ((((record.DuplicationKind == DuplicationKind.Prohibited) || (duplicationKind == DuplicationKind.Prohibited)) || ((record.DuplicationKind == DuplicationKind.NavigationProperty) && record.AssociationLinkFound)) || !this.allowDuplicateProperties) { throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(name)); } }
/// <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.AssociationLinkFound && !existingDuplicationRecord.NavigationLinkFound) { // 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> /// Check the <paramref name="property"/> 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="property">The property to be checked.</param> internal void CheckForDuplicatePropertyNames(ODataProperty property) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(property != null, "property != null"); #if DEBUG Debug.Assert(this.startNavigationLinkName == null, "CheckForDuplicatePropertyNamesOnNavigationLinkStart was followed by a CheckForDuplicatePropertyNames(ODataProperty)."); #endif string propertyName = property.Name; DuplicationKind duplicationKind = GetDuplicationKind(property); DuplicationRecord existingDuplicationRecord; if (!this.TryGetDuplicationRecord(propertyName, out existingDuplicationRecord)) { this.propertyNameCache.Add(propertyName, new DuplicationRecord(duplicationKind)); } else if (existingDuplicationRecord.DuplicationKind == DuplicationKind.PropertyAnnotationSeen) { existingDuplicationRecord.DuplicationKind = duplicationKind; } else { // If either of them prohibits duplication, fail // If the existing one is an association link, fail (association links don't allow duplicates with simple properties) // If we don't allow duplication in the first place, fail, since there is no valid case where a simple property coexists with anything else with the same name. if (existingDuplicationRecord.DuplicationKind == DuplicationKind.Prohibited || duplicationKind == DuplicationKind.Prohibited || (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty && existingDuplicationRecord.AssociationLink != null) || !this.allowDuplicateProperties) { throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName)); } else { // Otherwise allow the duplicate. // Note that we don't modify the existing duplication record in any way if the new property is a simple property. // This is because if the existing one is a simple property which allows duplication as well, there's nothing to change. // and if the existing one is a navigation property the navigation property information is more important than the simple property one. } } }
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; } }