Exemplo n.º 1
0
        internal string UriToUriString(Uri uri, bool makeAbsolute)
        {
            Uri uri2;

            if (base.UrlResolver != null)
            {
                uri2 = base.UrlResolver.ResolveUrl(base.MessageWriterSettings.BaseUri, uri);
                if (uri2 != null)
                {
                    return(UriUtilsCommon.UriToString(uri2));
                }
            }
            uri2 = uri;
            if (!uri2.IsAbsoluteUri)
            {
                if (makeAbsolute)
                {
                    if (base.MessageWriterSettings.BaseUri == null)
                    {
                        throw new ODataException(Strings.ODataWriter_RelativeUriUsedWithoutBaseUriSpecified(UriUtilsCommon.UriToString(uri)));
                    }
                    uri2 = UriUtils.UriToAbsoluteUri(base.MessageWriterSettings.BaseUri, uri);
                }
                else
                {
                    uri2 = UriUtils.EnsureEscapedRelativeUri(uri2);
                }
            }
            return(UriUtilsCommon.UriToString(uri2));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Validates that a string is either a valid absolute URI, or (if it begins with '#') it is a valid URI fragment.
        /// </summary>
        /// <param name="metadataDocumentUri">The metadata document uri.</param>
        /// <param name="propertyName">The property name to validate.</param>
        internal static void ValidateMetadataReferencePropertyName(Uri metadataDocumentUri, string propertyName)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(metadataDocumentUri != null, "metadataDocumentUri != null");
            Debug.Assert(metadataDocumentUri.IsAbsoluteUri, "metadataDocumentUri.IsAbsoluteUri");
            Debug.Assert(!String.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

            string uriStringToValidate = propertyName;

            // If it starts with a '#', validate that the rest of the string is a valid Uri fragment.
            if (propertyName[0] == JsonLightConstants.MetadataUriFragmentIndicator)
            {
                // In order to use System.Uri to validate a fragement, we first prepend the metadataDocumentUri
                // so that it becomes an absolute URI which we can validate with Uri.IsWellFormedUriString.
                uriStringToValidate = UriUtilsCommon.UriToString(metadataDocumentUri) + UriUtils.EnsureEscapedFragment(propertyName);
            }

            if (!Uri.IsWellFormedUriString(uriStringToValidate, UriKind.Absolute) ||
                !ODataJsonLightUtils.IsMetadataReferenceProperty(propertyName) ||
                propertyName[propertyName.Length - 1] == JsonLightConstants.MetadataUriFragmentIndicator)
            {
                throw new ODataException(Strings.ValidationUtils_InvalidMetadataReferenceProperty(propertyName));
            }

            if (IsOpenMetadataReferencePropertyName(metadataDocumentUri, propertyName))
            {
                throw new ODataException(Strings.ODataJsonLightValidationUtils_OpenMetadataReferencePropertyNotSupported(propertyName, UriUtilsCommon.UriToString(metadataDocumentUri)));
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Converts the given <paramref name="uri"/> Uri to a string.
        /// If the provided baseUri is not null and is a base Uri of the <paramref name="uri"/> Uri
        /// the method returns the string form of the relative Uri.
        /// </summary>
        /// <param name="uri">The Uri to convert.</param>
        /// <param name="failOnRelativeUriWithoutBaseUri">If set to true then this method will fail if the uri specified by <paramref name="uri"/> is relative
        /// and no base uri is specified.</param>
        /// <returns>The string form of the <paramref name="uri"/> Uri. If the Uri is absolute it returns the
        /// string form of the <paramref name="uri"/>. If the <paramref name="uri"/> Uri is not absolute
        /// it returns the original string of the Uri.</returns>
        internal string UriToUrlAttributeValue(Uri uri, bool failOnRelativeUriWithoutBaseUri)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(uri != null, "uri != null");

            if (this.UrlResolver != null)
            {
                // The resolver returns 'null' if no custom resolution is desired.
                Uri resultUri = this.UrlResolver.ResolveUrl(this.MessageWriterSettings.BaseUri, uri);
                if (resultUri != null)
                {
                    return(UriUtilsCommon.UriToString(resultUri));
                }
            }

            if (!uri.IsAbsoluteUri)
            {
                // NOTE: the only URIs that are allowed to be relative (e.g., failOnRelativeUriWithoutBaseUri is false)
                //       are metadata URIs in operations; for such metadata URIs there is no base URI.
                if (this.MessageWriterSettings.BaseUri == null && failOnRelativeUriWithoutBaseUri)
                {
                    throw new ODataException(
                              ODataErrorStrings.ODataWriter_RelativeUriUsedWithoutBaseUriSpecified(UriUtilsCommon.UriToString(uri)));
                }

                uri = UriUtils.EnsureEscapedRelativeUri(uri);
            }

            return(UriUtilsCommon.UriToString(uri));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Computes and sets the field for the computed Id.
        /// </summary>
        private void ComputeAndCacheId()
        {
            if (this.computedEntityInstanceUri == null)
            {
                Uri uri = this.uriBuilder.BuildBaseUri();
                uri = this.uriBuilder.BuildEntitySetUri(uri, this.entryMetadataContext.TypeContext.EntitySetName);
                uri = this.uriBuilder.BuildEntityInstanceUri(uri, this.entryMetadataContext.KeyProperties, this.entryMetadataContext.ActualEntityTypeName);

                this.computedEntityInstanceUri = uri;
                this.computedId = UriUtilsCommon.UriToString(uri);
            }
        }
Exemplo n.º 5
0
        /// <summary>Creates a URI suitable for host-agnostic comparison purposes.</summary>
        /// <param name="uri">URI to compare.</param>
        /// <returns>URI suitable for comparison.</returns>
        private static Uri CreateBaseComparableUri(Uri uri)
        {
            Debug.Assert(uri != null, "uri != null");

            uri = new Uri(UriUtilsCommon.UriToString(uri).ToUpper(CultureInfo.InvariantCulture), UriKind.RelativeOrAbsolute);

            UriBuilder builder = new UriBuilder(uri);

            builder.Host   = "h";
            builder.Port   = 80;
            builder.Scheme = "http";
            return(builder.Uri);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Determines if the specified property name is a name of an open metadata reference property.
        /// </summary>
        /// <param name="metadataDocumentUri">The metadata document uri.</param>
        /// <param name="propertyName">The property name in question.</param>
        /// <returns>true if the specified property name is a name of an open metadata reference property; false otherwise.</returns>
        internal static bool IsOpenMetadataReferencePropertyName(Uri metadataDocumentUri, string propertyName)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(metadataDocumentUri != null, "metadataDocumentUri != null");
            Debug.Assert(metadataDocumentUri.IsAbsoluteUri, "metadataDocumentUri.IsAbsoluteUri");
            Debug.Assert(!String.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

            // If a metadata reference property isn't based off of the known metadata document URI (for example, it points to a model on another server),
            // then it must be open. It is based off the known metadata document URI if it either is a fragment (i.e., starts with a hash) or starts with the known absolute URI.
            return(ODataJsonLightUtils.IsMetadataReferenceProperty(propertyName) &&
                   propertyName[0] != JsonLightConstants.MetadataUriFragmentIndicator &&
                   !propertyName.StartsWith(UriUtilsCommon.UriToString(metadataDocumentUri), StringComparison.OrdinalIgnoreCase));
        }
Exemplo n.º 7
0
        /// <summary>
        /// Validates an operation is valid.
        /// </summary>
        /// <param name="metadataDocumentUri">The metadata document uri.</param>
        /// <param name="operation">The operation to validate.</param>
        internal static void ValidateOperation(Uri metadataDocumentUri, ODataOperation operation)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(operation != null, "operation != null");

            ValidationUtils.ValidateOperationMetadataNotNull(operation);
            string name = UriUtilsCommon.UriToString(operation.Metadata);

            if (metadataDocumentUri != null)
            {
                Debug.Assert(metadataDocumentUri.IsAbsoluteUri, "metadataDocumentUri.IsAbsoluteUri");
                ValidateMetadataReferencePropertyName(metadataDocumentUri, name);
                Debug.Assert(!IsOpenMetadataReferencePropertyName(metadataDocumentUri, name), "!IsOpenMetadataReferencePropertyName(metadataDocumentUri, name)");
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Builds the entity instance URI with the given key property values.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="keyProperties">The list of name value pair for key properties.</param>
        /// <param name="entityTypeName">The full name of the entity type we are building the key expression for.</param>
        /// <returns>The entity instance URI.</returns>
        internal override Uri BuildEntityInstanceUri(Uri baseUri, ICollection <KeyValuePair <string, object> > keyProperties, string entityTypeName)
        {
            DebugUtils.CheckNoExternalCallers();

            ValidateBaseUri(baseUri);
            Debug.Assert(keyProperties != null, "keyProperties != null");
            Debug.Assert(!string.IsNullOrEmpty(entityTypeName), "!string.IsNullOrEmpty(entityTypeName)");

            StringBuilder builder = new StringBuilder(UriUtilsCommon.UriToString(baseUri));

            // TODO: What should be done about escaping the values.
            // TODO: What should happen if the URL does end with a slash?
            this.AppendKeyExpression(builder, keyProperties, entityTypeName);
            return(new Uri(builder.ToString(), UriKind.Absolute));
        }
Exemplo n.º 9
0
        private static Uri AppendSegment(Uri baseUri, string segment, bool escapeSegment)
        {
            string baseUriString = UriUtilsCommon.UriToString(baseUri);

            if (escapeSegment)
            {
                segment = Uri.EscapeDataString(segment);
            }

            if (baseUriString[baseUriString.Length - 1] != ODataConstants.UriSegmentSeparatorChar)
            {
                return(new Uri(baseUriString + ODataConstants.UriSegmentSeparator + segment, UriKind.Absolute));
            }
            else
            {
                return(new Uri(baseUri, segment));
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Returns the string representation of the URI
        /// </summary>
        /// <param name="uri">The uri to process.</param>
        /// <returns>Returns the string representation of the URI.</returns>
        internal string UriToString(Uri uri)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(uri != null, "uri != null");

            // Get the metadataDocumentUri directly from MessageWriterSettings and not using MetadataUriBuilder because in the case of getting the service document with nometadata
            // MetadataUriBuilder returns null, but the metadataDocumentUri is needed to calculate Absolute Uris in the service document. In any other case jsonLightOutputContext.CreateMetadataUriBuilder() should be used.
            ODataMetadataDocumentUri odataMetadataDocumentUri = this.jsonLightOutputContext.MessageWriterSettings.MetadataDocumentUri;
            Uri metadataDocumentUri = odataMetadataDocumentUri == null ? null : odataMetadataDocumentUri.BaseUri;

            Uri resultUri;

            if (this.jsonLightOutputContext.UrlResolver != null)
            {
                // The resolver returns 'null' if no custom resolution is desired.
                resultUri = this.jsonLightOutputContext.UrlResolver.ResolveUrl(metadataDocumentUri, uri);
                if (resultUri != null)
                {
                    return(UriUtilsCommon.UriToString(resultUri));
                }
            }

            resultUri = uri;
            if (!resultUri.IsAbsoluteUri)
            {
                if (!this.allowRelativeUri)
                {
                    if (metadataDocumentUri == null)
                    {
                        throw new ODataException(Strings.ODataJsonLightSerializer_RelativeUriUsedWithoutMetadataDocumentUriOrMetadata(UriUtilsCommon.UriToString(resultUri)));
                    }

                    resultUri = UriUtils.UriToAbsoluteUri(metadataDocumentUri, uri);
                }
                else
                {
                    resultUri = UriUtils.EnsureEscapedRelativeUri(resultUri);
                }
            }

            return(UriUtilsCommon.UriToString(resultUri));
        }
Exemplo n.º 11
0
 internal string UriToUrlAttributeValue(Uri uri, bool failOnRelativeUriWithoutBaseUri)
 {
     if (base.UrlResolver != null)
     {
         Uri uri2 = base.UrlResolver.ResolveUrl(base.MessageWriterSettings.BaseUri, uri);
         if (uri2 != null)
         {
             return(UriUtilsCommon.UriToString(uri2));
         }
     }
     if (!uri.IsAbsoluteUri)
     {
         if ((base.MessageWriterSettings.BaseUri == null) && failOnRelativeUriWithoutBaseUri)
         {
             throw new ODataException(Strings.ODataWriter_RelativeUriUsedWithoutBaseUriSpecified(UriUtilsCommon.UriToString(uri)));
         }
         uri = UriUtils.EnsureEscapedRelativeUri(uri);
     }
     return(UriUtilsCommon.UriToString(uri));
 }
        internal void WriteServiceDocument(ODataWorkspace defaultWorkspace)
        {
            IEnumerable <ODataResourceCollectionInfo> collections = defaultWorkspace.Collections;

            base.WriteTopLevelPayload(delegate {
                this.JsonWriter.StartObjectScope();
                this.JsonWriter.WriteName("EntitySets");
                this.JsonWriter.StartArrayScope();
                if (collections != null)
                {
                    foreach (ODataResourceCollectionInfo info in collections)
                    {
                        ValidationUtils.ValidateResourceCollectionInfo(info);
                        this.JsonWriter.WriteValue(UriUtilsCommon.UriToString(info.Url));
                    }
                }
                this.JsonWriter.EndArrayScope();
                this.JsonWriter.EndObjectScope();
            });
        }
Exemplo n.º 13
0
        /// <summary>
        /// Gets the metadata reference fragment from the operation metadata uri.
        /// i.e. if the operation metadata uri is {absolute metadata document uri}#{container-qualified-operation-name},
        /// this method will return #{container-qualified-operation-name}.
        /// </summary>
        /// <param name="operation">Operation in question.</param>
        /// <returns>The metadata reference fragment from the operation metadata uri.</returns>
        private string GetOperationMetadataString(ODataOperation operation)
        {
            Debug.Assert(operation != null && operation.Metadata != null, "operation != null && operation.Metadata != null");

            string operationMetadataString = UriUtilsCommon.UriToString(operation.Metadata);

            Debug.Assert(ODataJsonLightUtils.IsMetadataReferenceProperty(operationMetadataString), "ODataJsonLightUtils.IsMetadataReferenceProperty(operationMetadataString)");

            // If we don't have a metadata document URI (which is the case with nometadata mode), just write the string form of the Uri we were given.
            if (this.MetadataDocumentBaseUri == null)
            {
                return(operation.Metadata.Fragment);
            }

            Debug.Assert(
                !ODataJsonLightValidationUtils.IsOpenMetadataReferencePropertyName(this.MetadataDocumentBaseUri, operationMetadataString),
                "Open metadata reference property is not supported, we should have thrown before this point.");

            return(JsonLightConstants.MetadataUriFragmentIndicator + ODataJsonLightUtils.GetUriFragmentFromMetadataReferencePropertyName(this.MetadataDocumentBaseUri, operationMetadataString));
        }
        /// <summary>
        /// Writes a service document in JSON format.
        /// </summary>
        /// <param name="defaultWorkspace">The default workspace to write in the service document.</param>
        internal void WriteServiceDocument(ODataWorkspace defaultWorkspace)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(defaultWorkspace != null, "defaultWorkspace != null");

            IEnumerable <ODataResourceCollectionInfo> collections = defaultWorkspace.Collections;

            this.WriteTopLevelPayload(
                () =>
            {
                // "{"
                this.JsonWriter.StartObjectScope();

                // "EntitySets":
                this.JsonWriter.WriteName(JsonConstants.ODataServiceDocumentEntitySetsName);

                // "["
                this.JsonWriter.StartArrayScope();

                if (collections != null)
                {
                    foreach (ODataResourceCollectionInfo collectionInfo in collections)
                    {
                        // validate that the collection has a non-null url.
                        ValidationUtils.ValidateResourceCollectionInfo(collectionInfo);

                        // Note that this is an exception case; if the Base URI is missing we will still write the relative URI.
                        // We allow this because collections are specified to be the entity set names in JSON and
                        // there is no base Uri in JSON.
                        this.JsonWriter.WriteValue(UriUtilsCommon.UriToString(collectionInfo.Url));
                    }
                }

                // "]"
                this.JsonWriter.EndArrayScope();

                // "}"
                this.JsonWriter.EndObjectScope();
            });
        }
Exemplo n.º 15
0
        /// <summary>
        /// Returns the string representation of the URI; Converts the URI into an absolute URI if the <paramref name="makeAbsolute"/> parameter is set to true.
        /// </summary>
        /// <param name="uri">The uri to process.</param>
        /// <param name="makeAbsolute">true, if the URI needs to be translated into an absolute URI; false otherwise.</param>
        /// <returns>If the <paramref name="makeAbsolute"/> parameter is set to true, then a string representation of an absolute URI which is either the
        /// specified <paramref name="uri"/> if it was absolute, or it's a combination of the BaseUri and the relative <paramref name="uri"/>;
        /// otherwise a string representation of the specified <paramref name="uri"/>.
        /// </returns>
        /// <remarks>This method will fail if <paramref name="makeAbsolute"/> is set to true and the specified <paramref name="uri"/> is relative and there's no base URI available.</remarks>
        internal string UriToUriString(Uri uri, bool makeAbsolute)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(uri != null, "uri != null");

            Uri resultUri;

            if (this.UrlResolver != null)
            {
                // The resolver returns 'null' if no custom resolution is desired.
                resultUri = this.UrlResolver.ResolveUrl(this.MessageWriterSettings.BaseUri, uri);
                if (resultUri != null)
                {
                    return(UriUtilsCommon.UriToString(resultUri));
                }
            }

            resultUri = uri;

            if (!resultUri.IsAbsoluteUri)
            {
                if (makeAbsolute)
                {
                    if (this.MessageWriterSettings.BaseUri == null)
                    {
                        throw new ODataException(o.Strings.ODataWriter_RelativeUriUsedWithoutBaseUriSpecified(UriUtilsCommon.UriToString(uri)));
                    }

                    resultUri = UriUtils.UriToAbsoluteUri(this.MessageWriterSettings.BaseUri, uri);
                }
                else
                {
                    // NOTE: the only URIs that are allowed to be relative are metadata URIs
                    //       in operations; for such metadata URIs there is no base URI.
                    resultUri = UriUtils.EnsureEscapedRelativeUri(resultUri);
                }
            }

            return(UriUtilsCommon.UriToString(resultUri));
        }
Exemplo n.º 16
0
        /// <summary>
        /// Returns a hash set of function imports (actions and functions) in the given entry.
        /// </summary>
        /// <param name="entry">The entry in question.</param>
        /// <param name="model">The edm model to resolve function imports.</param>
        /// <param name="metadataDocumentUri">The metadata document uri.</param>
        /// <returns>The hash set of function imports (actions and functions) in the given entry.</returns>
        private static HashSet <IEdmFunctionImport> GetFunctionImportsInEntry(ODataEntry entry, IEdmModel model, Uri metadataDocumentUri)
        {
            Debug.Assert(entry != null, "entry != null");
            Debug.Assert(model != null, "model != null");
            Debug.Assert(metadataDocumentUri != null && metadataDocumentUri.IsAbsoluteUri, "metadataDocumentUri != null && metadataDocumentUri.IsAbsoluteUri");

            HashSet <IEdmFunctionImport> functionImportsInEntry = new HashSet <IEdmFunctionImport>(EqualityComparer <IEdmFunctionImport> .Default);
            IEnumerable <ODataOperation> operations             = ODataUtilsInternal.ConcatEnumerables((IEnumerable <ODataOperation>)entry.NonComputedActions, (IEnumerable <ODataOperation>)entry.NonComputedFunctions);

            if (operations != null)
            {
                foreach (ODataOperation operation in operations)
                {
                    Debug.Assert(operation.Metadata != null, "operation.Metadata != null");
                    string operationMetadataString = UriUtilsCommon.UriToString(operation.Metadata);
                    Debug.Assert(
                        ODataJsonLightUtils.IsMetadataReferenceProperty(operationMetadataString),
                        "ODataJsonLightUtils.IsMetadataReferenceProperty(operationMetadataString)");
                    Debug.Assert(
                        operationMetadataString[0] == JsonLightConstants.MetadataUriFragmentIndicator || metadataDocumentUri.IsBaseOf(operation.Metadata),
                        "operationMetadataString[0] == JsonLightConstants.MetadataUriFragmentIndicator || metadataDocumentUri.IsBaseOf(operation.Metadata)");

                    string fullyQualifiedOperationName = ODataJsonLightUtils.GetUriFragmentFromMetadataReferencePropertyName(metadataDocumentUri, operationMetadataString);
                    IEnumerable <IEdmFunctionImport> functionImports = model.ResolveFunctionImports(fullyQualifiedOperationName);
                    if (functionImports != null)
                    {
                        foreach (IEdmFunctionImport functionImport in functionImports)
                        {
                            functionImportsInEntry.Add(functionImport);
                        }
                    }
                }
            }

            return(functionImportsInEntry);
        }
Exemplo n.º 17
0
        internal override string GetId()
        {
            DebugUtils.CheckNoExternalCallers();

            // If the Id, ReadLink, or EditLink were on the wire (in that order), use that wire value for the Id.
            // Otherwise compute it based on the key values. We specifically do not want to use the ReadLink/EditLink
            // values if they were already previously computed instead of just being directly set on the entry.
            if (this.entryMetadataContext.Entry.HasNonComputedId)
            {
                return(this.entryMetadataContext.Entry.NonComputedId);
            }

            if (this.entryMetadataContext.Entry.HasNonComputedReadLink)
            {
                return(UriUtilsCommon.UriToString(this.entryMetadataContext.Entry.NonComputedReadLink));
            }

            if (this.entryMetadataContext.Entry.NonComputedEditLink != null)
            {
                return(UriUtilsCommon.UriToString(this.entryMetadataContext.Entry.NonComputedEditLink));
            }

            return(this.ComputedId);
        }
Exemplo n.º 18
0
        /// <summary>
        /// Resolves a navigation property name to an IEdmNavigationProperty.
        /// </summary>
        /// <param name="entityType">Entity Type to look for the navigation property on.</param>
        /// <param name="navigationPropertyName">Navigation property name to find.</param>
        /// <returns>Returns the navigation property of throws an exception if it cannot be found.</returns>
        private IEdmNavigationProperty ResolveNavigationProperty(IEdmEntityType entityType, string navigationPropertyName)
        {
            IEdmNavigationProperty navigationProperty = null;
            IEdmProperty           property           = entityType.FindProperty(navigationPropertyName);

            navigationProperty = property as IEdmNavigationProperty;

            if (navigationProperty == null)
            {
                throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidPropertyForEntityReferenceLinkUri(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), navigationPropertyName));
            }

            return(navigationProperty);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Applies the model and validates the metadata URI against it.
        /// </summary>
        /// <param name="expectedPayloadKind">The payload kind we expect the metadata URI to conform to.</param>
        /// <param name="readerBehavior">Reader behavior if the caller is a reader, null if no reader behavior is available.</param>
        /// <param name="version">The version of the payload being read.</param>
        private void ParseMetadataUri(ODataPayloadKind expectedPayloadKind, ODataReaderBehavior readerBehavior, ODataVersion version)
        {
            ODataPayloadKind detectedPayloadKind = this.ParseMetadataUriFragment(this.parseResult.Fragment, readerBehavior, version);

            // unsupported payload kind indicates that this is during payload kind detection, so we should not fail.
            bool detectedPayloadKindMatchesExpectation = detectedPayloadKind == expectedPayloadKind || expectedPayloadKind == ODataPayloadKind.Unsupported;

            if (detectedPayloadKind == ODataPayloadKind.Collection)
            {
                // If the detected payload kind is 'collection' it can always also be treated as a property.
                this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Collection, ODataPayloadKind.Property };
                if (expectedPayloadKind == ODataPayloadKind.Property)
                {
                    detectedPayloadKindMatchesExpectation = true;
                }
            }
            else
            {
                this.parseResult.DetectedPayloadKinds = new[] { detectedPayloadKind };
            }

            // If the expected and detected payload kinds don't match and we are not running payload kind detection
            // right now (payloadKind == ODataPayloadKind.Unsupported) and we did not detect a collection kind for
            // an expected property kind (which is allowed), fail.
            if (!detectedPayloadKindMatchesExpectation)
            {
                throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_MetadataUriDoesNotMatchExpectedPayloadKind(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), expectedPayloadKind.ToString()));
            }

            // NOTE: we interpret an empty select query option to mean that nothing should be projected
            //       (whereas a missing select query option means everything should be projected).
            string selectQueryOption = this.parseResult.SelectQueryOption;

            if (selectQueryOption != null)
            {
                if (detectedPayloadKind != ODataPayloadKind.Feed && detectedPayloadKind != ODataPayloadKind.Entry)
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidPayloadKindWithSelectQueryOption(expectedPayloadKind.ToString()));
                }
            }
        }
Exemplo n.º 20
0
        private ODataPayloadKind ParseMetadataUriFragment(string fragment, ODataReaderBehavior readerBehavior, ODataVersion version)
        {
            // remove any query options like $select that may have been embedded in the fragment.
            int indexOfQueryOptionSeparator = fragment.IndexOf(JsonLightConstants.MetadataUriQueryOptionSeparator);

            if (indexOfQueryOptionSeparator > 0)
            {
                // Extract the $select query option value from the fragment if it exists
                string fragmentQueryOptions = fragment.Substring(indexOfQueryOptionSeparator);
                this.parseResult.SelectQueryOption = ExtractSelectQueryOption(fragmentQueryOptions);

                fragment = fragment.Substring(0, indexOfQueryOptionSeparator);
            }

            string[] parts     = fragment.Split(JsonLightConstants.MetadataUriFragmentPartSeparator);
            int      partCount = parts.Length;

            ODataPayloadKind detectedPayloadKind = ODataPayloadKind.Unsupported;
            EdmTypeResolver  edmTypeResolver     = new EdmTypeReaderResolver(this.model, readerBehavior, version);

            var foundAssociationLinksSegment = fragment.IndexOf(ODataConstants.AssociationLinkSegmentName, StringComparison.Ordinal);

            if (foundAssociationLinksSegment > -1)
            {
                detectedPayloadKind = this.ParseAssociationLinks(edmTypeResolver, partCount, parts, readerBehavior, version);
            }
            else
            {
                switch (partCount)
                {
                case 1:
                    // Service document: no fragment
                    if (fragment.Length == 0)
                    {
                        detectedPayloadKind = ODataPayloadKind.ServiceDocument;
                        break;
                    }

                    if (parts[0].Equals(JsonLightConstants.MetadataUriFragmentNull, StringComparison.OrdinalIgnoreCase))
                    {
                        detectedPayloadKind             = ODataPayloadKind.Property;
                        this.parseResult.IsNullProperty = true;
                        break;
                    }

                    IEdmEntitySet entitySet = this.model.ResolveEntitySet(parts[0]);
                    if (entitySet != null)
                    {
                        // Feed: {schema.entity-container.entity-set}
                        this.parseResult.EntitySet = entitySet;
                        this.parseResult.EdmType   = edmTypeResolver.GetElementType(entitySet);
                        detectedPayloadKind        = ODataPayloadKind.Feed;
                        break;
                    }

                    // Property: {schema.type} or Collection({schema.type}) where schema.type is primitive or complex.
                    this.parseResult.EdmType = this.ResolveType(parts[0], readerBehavior, version);
                    Debug.Assert(
                        this.parseResult.EdmType.TypeKind == EdmTypeKind.Primitive || this.parseResult.EdmType.TypeKind == EdmTypeKind.Complex || this.parseResult.EdmType.IsNonEntityCollectionType(),
                        "The first metadata URI segment must be a set or a non-entity type.");
                    detectedPayloadKind = this.parseResult.EdmType is IEdmCollectionType ? ODataPayloadKind.Collection : ODataPayloadKind.Property;

                    break;

                case 2:
                    // Entry: {schema.entity-container.entity-set}/@Element
                    // Feed with type cast: {schema.entity-container.entity-set}/{type-cast}
                    detectedPayloadKind = this.ResolveEntitySet(
                        parts[0],
                        (IEdmEntitySet resolvedEntitySet) =>
                    {
                        IEdmEntityType entitySetElementType = edmTypeResolver.GetElementType(resolvedEntitySet);

                        if (string.CompareOrdinal(JsonLightConstants.MetadataUriFragmentItemSelector, parts[1]) == 0)
                        {
                            this.parseResult.EdmType = entitySetElementType;
                            return(ODataPayloadKind.Entry);
                        }
                        else
                        {
                            this.parseResult.EdmType = this.ResolveTypeCast(resolvedEntitySet, parts[1], readerBehavior, version, entitySetElementType);
                            return(ODataPayloadKind.Feed);
                        }
                    });

                    break;

                case 3:
                    detectedPayloadKind = this.ResolveEntitySet(
                        parts[0],
                        (IEdmEntitySet resolvedEntitySet) =>
                    {
                        IEdmEntityType entitySetElementType = edmTypeResolver.GetElementType(resolvedEntitySet);

                        // Entry with type cast: {schema.entity-container.entity-set}/{type-cast}/@Element
                        this.parseResult.EdmType = this.ResolveTypeCast(resolvedEntitySet, parts[1], readerBehavior, version, entitySetElementType);
                        this.ValidateMetadataUriFragmentItemSelector(parts[2]);
                        return(ODataPayloadKind.Entry);
                    });

                    break;

                default:
                    throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_FragmentWithInvalidNumberOfParts(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), partCount, 3));
                }
            }

            return(detectedPayloadKind);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Returns the parse results of the metadata uri if it has a AssociationLink in the uri
        /// </summary>
        /// <param name="edmTypeResolver">Edm Type Resolver to determine entityset type element.</param>
        /// <param name="partCount">Number of split parts the metadata fragment is split into.</param>
        /// <param name="parts">The  actual metadata fragment parts.</param>
        /// <param name="readerBehavior">The reader behavior.</param>
        /// <param name="version">The odata version.</param>
        /// <returns>Returns with an EntityReferenceLink or Links depending on the Uri, sets the parse results with the navigation, and set</returns>
        private ODataPayloadKind ParseAssociationLinks(EdmTypeResolver edmTypeResolver, int partCount, string[] parts, ODataReaderBehavior readerBehavior, ODataVersion version)
        {
            return(this.ResolveEntitySet(
                       parts[0],
                       (IEdmEntitySet resolvedEntitySet) =>
            {
                ODataPayloadKind detectedPayloadKind = ODataPayloadKind.Unsupported;
                IEdmNavigationProperty navigationProperty;
                switch (partCount)
                {
                case 3:
                    if (string.CompareOrdinal(ODataConstants.AssociationLinkSegmentName, parts[1]) == 0)
                    {
                        // Entity reference links: {schema.entity-container.entity-set}/$links/{nav-property}
                        navigationProperty = this.ResolveEntityReferenceLinkMetadataFragment(edmTypeResolver, resolvedEntitySet, (string)null, parts[2], readerBehavior, version);
                        detectedPayloadKind = this.SetEntityLinkParseResults(navigationProperty, null);
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidAssociationLink(UriUtilsCommon.UriToString(this.parseResult.MetadataUri)));
                    }

                    break;

                case 4:
                    if (string.CompareOrdinal(ODataConstants.AssociationLinkSegmentName, parts[1]) == 0)
                    {
                        // Entry with property: {schema.entity-container.entity-set}/$links/{col-nav-property}/@Element
                        // Entry with property: {schema.entity-container.entity-set}/$links/{ref-nav-property}/@Element (invalid, will throw)
                        navigationProperty = this.ResolveEntityReferenceLinkMetadataFragment(edmTypeResolver, resolvedEntitySet, null, parts[2], readerBehavior, version);
                        this.ValidateLinkMetadataUriFragmentItemSelector(parts[3]);
                        detectedPayloadKind = this.SetEntityLinkParseResults(navigationProperty, parts[3]);
                    }
                    else if (string.CompareOrdinal(ODataConstants.AssociationLinkSegmentName, parts[2]) == 0)
                    {
                        // Entry with property: {schema.entity-container.entity-set}/type/$links/{colproperty}
                        navigationProperty = this.ResolveEntityReferenceLinkMetadataFragment(edmTypeResolver, resolvedEntitySet, parts[1], parts[3], readerBehavior, version);
                        detectedPayloadKind = this.SetEntityLinkParseResults(navigationProperty, null);
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidAssociationLink(UriUtilsCommon.UriToString(this.parseResult.MetadataUri)));
                    }

                    break;

                case 5:
                    if (string.CompareOrdinal(ODataConstants.AssociationLinkSegmentName, parts[2]) == 0)
                    {
                        // Entry with property: {schema.entity-container.entity-set}/type/$links/{navproperty}/@Element
                        navigationProperty = this.ResolveEntityReferenceLinkMetadataFragment(edmTypeResolver, resolvedEntitySet, parts[1], parts[3], readerBehavior, version);
                        this.ValidateLinkMetadataUriFragmentItemSelector(parts[2]);
                        detectedPayloadKind = this.SetEntityLinkParseResults(navigationProperty, parts[4]);
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidAssociationLink(UriUtilsCommon.UriToString(this.parseResult.MetadataUri)));
                    }

                    break;

                default:
                    throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidAssociationLink(UriUtilsCommon.UriToString(this.parseResult.MetadataUri)));
                }

                return detectedPayloadKind;
            }));
        }
Exemplo n.º 22
0
        /// <summary>
        /// Resolves a type.
        /// </summary>
        /// <param name="typeName">The type name.</param>
        /// <param name="readerBehavior">Reader behavior if the caller is a reader, null if no reader behavior is available.</param>
        /// <param name="version">The version of the payload being read.</param>
        /// <returns>The resolved Edm type.</returns>
        private IEdmType ResolveType(string typeName, ODataReaderBehavior readerBehavior, ODataVersion version)
        {
            string typeNameToResolve = EdmLibraryExtensions.GetCollectionItemTypeName(typeName) ?? typeName;

            EdmTypeKind typeKind;
            IEdmType    resolvedType = MetadataUtils.ResolveTypeNameForRead(this.model, /*expectedType*/ null, typeNameToResolve, readerBehavior, version, out typeKind);

            if (resolvedType == null || resolvedType.TypeKind != EdmTypeKind.Primitive && resolvedType.TypeKind != EdmTypeKind.Complex)
            {
                throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidEntitySetNameOrTypeName(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), typeName));
            }

            resolvedType = typeNameToResolve == typeName ? resolvedType : EdmLibraryExtensions.GetCollectionType(resolvedType.ToTypeReference(true /*nullable*/));
            return(resolvedType);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Resolves an entity set with an optional type cast and updates the parse result.
        /// </summary>
        /// <param name="entitySet">The entity set to resolve the type cast against.</param>
        /// <param name="typeCast">The optional type cast.</param>
        /// <param name="readerBehavior">Reader behavior if the caller is a reader, null if no reader behavior is available.</param>
        /// <param name="version">The version of the payload being read.</param>
        /// <param name="entitySetElementType">The type of the given entity set.</param>
        /// <returns>The resolved entity type.</returns>
        private IEdmEntityType ResolveTypeCast(IEdmEntitySet entitySet, string typeCast, ODataReaderBehavior readerBehavior, ODataVersion version, IEdmEntityType entitySetElementType)
        {
            Debug.Assert(entitySet != null, "entitySet != null");

            IEdmEntityType entityType = entitySetElementType;

            // Parse the type cast if it exists
            if (!string.IsNullOrEmpty(typeCast))
            {
                EdmTypeKind typeKind;
                entityType = MetadataUtils.ResolveTypeNameForRead(this.model, /*expectedType*/ null, typeCast, readerBehavior, version, out typeKind) as IEdmEntityType;
                if (entityType == null)
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidEntityTypeInTypeCast(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), typeCast));
                }

                // Validate that the entity type is assignable to the base type of the set
                if (!entitySetElementType.IsAssignableFrom(entityType))
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_IncompatibleEntityTypeInTypeCast(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), typeCast, entitySetElementType.FullName(), entitySet.FullName()));
                }
            }

            return(entityType);
        }
Exemplo n.º 24
0
        /// <summary>
        /// Resolves the entity set.
        /// </summary>
        /// <param name="entitySetPart">The entity set part.</param>
        /// <param name="resolvedEntitySet">The resolved entity set.</param>
        /// <returns>Returns the OData Payload Kind</returns>
        private ODataPayloadKind ResolveEntitySet(string entitySetPart, Func <IEdmEntitySet, ODataPayloadKind> resolvedEntitySet)
        {
            IEdmEntitySet entitySet = this.model.ResolveEntitySet(entitySetPart);

            if (entitySet != null)
            {
                this.parseResult.EntitySet = entitySet;
                return(resolvedEntitySet(entitySet));
            }

            throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidEntitySetName(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), entitySetPart));
        }
Exemplo n.º 25
0
        /// <summary>
        /// Set the EntityLinks Parse results.
        /// </summary>
        /// <param name="navigationProperty">Navigation property to add to the results.</param>
        /// <param name="singleElement">Single element string, used to confirm if this is an error case or not.</param>
        /// <returns>Returns ReferenceLink or Collection Link based on the navigation and at element</returns>
        private ODataPayloadKind SetEntityLinkParseResults(IEdmNavigationProperty navigationProperty, string singleElement)
        {
            ODataPayloadKind detectedPayloadKind = ODataPayloadKind.Unsupported;

            this.parseResult.NavigationProperty = navigationProperty;

            detectedPayloadKind = navigationProperty.Type.IsCollection() ? ODataPayloadKind.EntityReferenceLinks : ODataPayloadKind.EntityReferenceLink;

            if (singleElement != null && string.CompareOrdinal(JsonLightConstants.MetadataUriFragmentItemSelector, singleElement) == 0)
            {
                if (navigationProperty.Type.IsCollection())
                {
                    detectedPayloadKind = ODataPayloadKind.EntityReferenceLink;
                }
                else
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidSingletonNavPropertyForEntityReferenceLinkUri(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), navigationProperty.Name, singleElement));
                }
            }

            return(detectedPayloadKind);
        }
Exemplo n.º 26
0
 /// <summary>
 /// Validate the Metadata Uri Fragment is @Element for a non $links metadata uri, throws if its not correct
 /// </summary>
 /// <param name="elementSelector">Element selector.</param>
 private void ValidateMetadataUriFragmentItemSelector(string elementSelector)
 {
     if (string.CompareOrdinal(JsonLightConstants.MetadataUriFragmentItemSelector, elementSelector) != 0)
     {
         throw new ODataException(ODataErrorStrings.ODataJsonLightMetadataUriParser_InvalidEntityWithTypeCastUriSuffix(UriUtilsCommon.UriToString(this.parseResult.MetadataUri), elementSelector, JsonLightConstants.MetadataUriFragmentItemSelector));
     }
 }