diff --git a/.editorconfig b/.editorconfig
index fc328cb5e..d650df54f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -3,3 +3,6 @@
# IDE0009: Member access should be qualified.
dotnet_diagnostic.IDE0009.severity = none
dotnet_diagnostic.CA2016.severity = warning
+
+[*.cs]
+dotnet_public_api_analyzer.require_api_files = true
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/CryptographyExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Common/CryptographyExtensions.cs
index de93a5cba..249db5591 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/CryptographyExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/CryptographyExtensions.cs
@@ -22,7 +22,7 @@ public static string GetHashSHA256(this string input)
Utils.CheckArgumentNull(input, nameof(input));
var inputBytes = Encoding.UTF8.GetBytes(input);
- var hashBytes = hasher.Value.ComputeHash(inputBytes);
+ if (hasher.Value?.ComputeHash(inputBytes) is not {} hashBytes) return string.Empty;
var hash = new StringBuilder();
foreach (var b in hashBytes)
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs b/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs
index b3cdf8ed4..1603761c7 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs
@@ -23,7 +23,7 @@ internal static class EdmModelHelper
/// Adds the derived types references together with their base type reference in the OneOf property of an OpenAPI schema.
///
/// The OpenAPI schema with the list of derived types references and their base type references set in the OneOf property.
- internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType structuredType, IEdmModel edmModel, OpenApiDocument document)
+ internal static OpenApiSchema? GetDerivedTypesReferenceSchema(IEdmStructuredType structuredType, IEdmModel edmModel, OpenApiDocument document)
{
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
Utils.CheckArgumentNull(edmModel, nameof(edmModel));
@@ -38,7 +38,7 @@ internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType
OpenApiSchema schema = new()
{
- OneOf = new List()
+ OneOf = []
};
var baseTypeSchema = new OpenApiSchemaReference(schemaElement.FullName(), document);
@@ -48,7 +48,7 @@ internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType
{
var derivedTypeSchema = new OpenApiSchemaReference(derivedType.FullName(), document);
schema.OneOf.Add(derivedTypeSchema);
- };
+ }
return schema;
}
@@ -60,8 +60,8 @@ internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType
/// The .
/// true, if navigability is allowed, otherwise false.
internal static bool NavigationRestrictionsAllowsNavigability(
- NavigationRestrictionsType restrictionType,
- NavigationPropertyRestriction restrictionProperty)
+ NavigationRestrictionsType? restrictionType,
+ NavigationPropertyRestriction? restrictionProperty)
{
// Verify using individual navigation restriction first
if (restrictionProperty?.Navigability != null && restrictionProperty.Navigability.Value == NavigationType.None)
@@ -82,7 +82,7 @@ internal static bool NavigationRestrictionsAllowsNavigability(
/// The OData context.
/// Optional: Identifier indicating whether it is a collection-valued non-indexed or single-valued navigation property.
/// The operation id generated from the given navigation property path.
- internal static string GenerateNavigationPropertyPathOperationId(ODataPath path, ODataContext context, string prefix = null)
+ internal static string? GenerateNavigationPropertyPathOperationId(ODataPath path, ODataContext context, string? prefix = null)
{
IList items = RetrieveNavigationPropertyPathsOperationIdSegments(path, context);
@@ -95,9 +95,9 @@ internal static string GenerateNavigationPropertyPathOperationId(ODataPath path,
{
items[lastItemIndex] = prefix + Utils.UpperFirstChar(items[lastItemIndex]);
}
- else
+ else if (Utils.UpperFirstChar(items[lastItemIndex]) is string lastIdentifier)
{
- items[lastItemIndex] = Utils.UpperFirstChar(items[lastItemIndex]);
+ items[lastItemIndex] = lastIdentifier;
}
return GenerateNavigationPropertyPathOperationId(items);
@@ -110,24 +110,22 @@ internal static string GenerateNavigationPropertyPathOperationId(ODataPath path,
/// The OData context.
/// Optional: Identifier indicating whether it is a collection-valued or single-valued complex property.
/// The operation id generated from the given complex property path.
- internal static string GenerateComplexPropertyPathOperationId(ODataPath path, ODataContext context, string prefix = null)
+ internal static string? GenerateComplexPropertyPathOperationId(ODataPath path, ODataContext context, string? prefix = null)
{
IList items = RetrieveNavigationPropertyPathsOperationIdSegments(path, context);
if (!items.Any())
return null;
- ODataComplexPropertySegment lastSegment = path.Segments.Skip(1).OfType()?.Last();
- Utils.CheckArgumentNull(lastSegment, nameof(lastSegment));
-
- if (!string.IsNullOrEmpty(prefix))
- {
- items.Add(prefix + Utils.UpperFirstChar(lastSegment?.Identifier));
- }
- else
- {
- items.Add(Utils.UpperFirstChar(lastSegment?.Identifier));
- }
+ if (path.Segments.Skip(1).OfType()?.Last()?.Identifier is string lastSegmentIdentifier)
+ if (!string.IsNullOrEmpty(prefix))
+ {
+ items.Add(prefix + Utils.UpperFirstChar(lastSegmentIdentifier));
+ }
+ else if (Utils.UpperFirstChar(lastSegmentIdentifier) is string lastIdentifier)
+ {
+ items.Add(lastIdentifier);
+ }
return GenerateNavigationPropertyPathOperationId(items);
}
@@ -137,7 +135,7 @@ internal static string GenerateComplexPropertyPathOperationId(ODataPath path, OD
///
/// The list of string values.
/// The generated navigation property operation id.
- private static string GenerateNavigationPropertyPathOperationId(IList items)
+ private static string? GenerateNavigationPropertyPathOperationId(IList items)
{
if (!items.Any())
return null;
@@ -155,10 +153,10 @@ internal static IList RetrieveNavigationPropertyPathsOperationIdSegments
{
Utils.CheckArgumentNull(path, nameof(path));
- IEdmNavigationSource navigationSource = (path.FirstSegment as ODataNavigationSourceSegment)?.NavigationSource;
- Utils.CheckArgumentNull(navigationSource, nameof(navigationSource));
+ if (path.FirstSegment is not ODataNavigationSourceSegment {NavigationSource: IEdmNavigationSource navigationSource})
+ throw new InvalidOperationException("The first segment of the path is not a navigation source segment.");
- IList items = new List
+ var items = new List
{
navigationSource.Name
};
@@ -174,7 +172,7 @@ s is ODataOperationSegment ||
s is ODataKeySegment);
Utils.CheckArgumentNull(segments, nameof(segments));
- string previousTypeCastSegmentId = null;
+ string? previousTypeCastSegmentId = null;
string pathHash = string.Empty;
foreach (var segment in segments)
@@ -185,15 +183,18 @@ s is ODataOperationSegment ||
}
else if (segment is ODataTypeCastSegment typeCastSegment
&& path.Kind != ODataPathKind.TypeCast // ex: ~/NavSource/NavProp/TypeCast
- && !(path.Kind == ODataPathKind.DollarCount && path.Segments.ElementAt(path.Segments.Count - 2)?.Kind == ODataSegmentKind.TypeCast)) // ex: ~/NavSource/NavProp/TypeCast/$count
+ && !(path.Kind == ODataPathKind.DollarCount && path.Segments[path.Segments.Count - 2]?.Kind == ODataSegmentKind.TypeCast)) // ex: ~/NavSource/NavProp/TypeCast/$count
{
// Only the last OData type cast segment identifier is added to the operation id
- items.Remove(previousTypeCastSegmentId);
- IEdmSchemaElement schemaElement = typeCastSegment.StructuredType as IEdmSchemaElement;
- previousTypeCastSegmentId = "As" + Utils.UpperFirstChar(schemaElement.Name);
- items.Add(previousTypeCastSegmentId);
+ if (!string.IsNullOrEmpty(previousTypeCastSegmentId))
+ items.Remove(previousTypeCastSegmentId);
+ if (typeCastSegment.StructuredType is IEdmSchemaElement schemaElement)
+ {
+ previousTypeCastSegmentId = "As" + Utils.UpperFirstChar(schemaElement.Name);
+ items.Add(previousTypeCastSegmentId);
+ }
}
- else if (segment is ODataOperationSegment operationSegment)
+ else if (segment is ODataOperationSegment operationSegment && !string.IsNullOrEmpty(operationSegment.Identifier))
{
// Navigation property generated via composable function
if (operationSegment.Operation is IEdmFunction function && context.Model.IsOperationOverload(function))
@@ -239,19 +240,20 @@ internal static string GenerateNavigationPropertyPathTagName(ODataPath path, ODa
Utils.CheckArgumentNull(path, nameof(path));
Utils.CheckArgumentNull(context, nameof(context));
- IEdmNavigationSource navigationSource = (path.FirstSegment as ODataNavigationSourceSegment)?.NavigationSource;
+ if (path.FirstSegment is not ODataNavigationSourceSegment {NavigationSource: IEdmNavigationSource navigationSource })
+ throw new InvalidOperationException("The first segment of the path is not a navigation source segment.");
- IList items = new List
+ var items = new List
{
navigationSource.Name
};
- IEdmNavigationProperty navigationProperty = path.OfType()?.Last()?.NavigationProperty;
- Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
+ if (path.OfType()?.Last()?.NavigationProperty is not IEdmNavigationProperty navigationProperty)
+ throw new InvalidOperationException("The last segment of the path is not a navigation property segment.");
- foreach (var segment in path.Segments.Skip(1).OfType())
+ foreach (var segment in path.Segments.Skip(1).OfType().Select(static x => x.NavigationProperty))
{
- if (segment.NavigationProperty == navigationProperty)
+ if (segment == navigationProperty)
{
items.Add(navigationProperty.ToEntityType().Name);
break;
@@ -260,12 +262,12 @@ internal static string GenerateNavigationPropertyPathTagName(ODataPath path, ODa
{
if (items.Count >= context.Settings.TagDepth - 1)
{
- items.Add(segment.NavigationProperty.ToEntityType().Name);
+ items.Add(segment.ToEntityType().Name);
break;
}
else
{
- items.Add(segment.NavigationProperty.Name);
+ items.Add(segment.Name);
}
}
}
@@ -284,12 +286,12 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
Utils.CheckArgumentNull(path, nameof(path));
Utils.CheckArgumentNull(context, nameof(context));
- ODataComplexPropertySegment complexSegment = path.Segments.OfType()?.Last();
- Utils.CheckArgumentNull(complexSegment, nameof(complexSegment));
+ if (path.Segments.OfType()?.Last() is not ODataComplexPropertySegment complexSegment)
+ throw new InvalidOperationException("The last segment of the path is not a complex property segment.");
// Get the segment before the last complex type segment
int complexSegmentIndex = path.Segments.IndexOf(complexSegment);
- ODataSegment preComplexSegment = path.Segments.ElementAt(complexSegmentIndex - 1);
+ ODataSegment preComplexSegment = path.Segments[complexSegmentIndex - 1];
int preComplexSegmentIndex = path.Segments.IndexOf(preComplexSegment);
while (preComplexSegment is ODataTypeCastSegment)
@@ -297,10 +299,10 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
// Skip this segment,
// Tag names don't include OData type cast segment identifiers
preComplexSegmentIndex--;
- preComplexSegment = path.Segments.ElementAt(preComplexSegmentIndex);
+ preComplexSegment = path.Segments[preComplexSegmentIndex];
}
- string tagName = null;
+ string? tagName = null;
if (preComplexSegment is ODataNavigationSourceSegment sourceSegment)
{
@@ -312,7 +314,7 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
}
else if (preComplexSegment is ODataKeySegment)
{
- var prevKeySegment = path.Segments.ElementAt(preComplexSegmentIndex - 1);
+ var prevKeySegment = path.Segments[preComplexSegmentIndex - 1];
if (prevKeySegment is ODataNavigationPropertySegment)
{
tagName = GenerateNavigationPropertyPathTagName(path, context);
@@ -323,9 +325,9 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
}
}
- List tagNameItems = tagName?.Split('.').ToList();
+ List tagNameItems = tagName?.Split('.').ToList() ?? [];
- if (tagNameItems.Count < context.Settings.TagDepth)
+ if (tagNameItems.Count < context.Settings.TagDepth && complexSegment.ComplexType is not null)
{
tagNameItems.Add(complexSegment.ComplexType.Name);
}
@@ -340,41 +342,41 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
/// The OData context.
/// Optional: Whether to include the List or Get prefix to the generated operation id.
/// The operation id prefix generated from the OData type cast path.
- internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path, ODataContext context, bool includeListOrGetPrefix = true)
+ internal static string? GenerateODataTypeCastPathOperationIdPrefix(ODataPath path, ODataContext context, bool includeListOrGetPrefix = true)
{
// Get the segment before the last OData type cast segment
- ODataTypeCastSegment typeCastSegment = path.Segments.OfType()?.Last();
- Utils.CheckArgumentNull(typeCastSegment, nameof(typeCastSegment));
+ if (path.Segments.OfType()?.Last() is not ODataTypeCastSegment typeCastSegment)
+ throw new InvalidOperationException("The last segment of the path is not a type cast segment.");
int typeCastSegmentIndex = path.Segments.IndexOf(typeCastSegment);
// The segment 1 place before the last OData type cast segment
- ODataSegment secondLastSegment = path.Segments.ElementAt(typeCastSegmentIndex - 1);
+ ODataSegment secondLastSegment = path.Segments[typeCastSegmentIndex - 1];
bool isIndexedCollValuedNavProp = false;
if (secondLastSegment is ODataKeySegment)
{
// The segment 2 places before the last OData type cast segment
- ODataSegment thirdLastSegment = path.Segments.ElementAt(typeCastSegmentIndex - 2);
+ ODataSegment thirdLastSegment = path.Segments[typeCastSegmentIndex - 2];
if (thirdLastSegment is ODataNavigationPropertySegment)
{
isIndexedCollValuedNavProp = true;
}
}
- ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
- IEdmSingleton singleton = navigationSourceSegment?.NavigationSource as IEdmSingleton;
- IEdmEntitySet entitySet = navigationSourceSegment?.NavigationSource as IEdmEntitySet;
+ ODataNavigationSourceSegment? navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
+ IEdmSingleton? singleton = navigationSourceSegment?.NavigationSource as IEdmSingleton;
+ IEdmEntitySet? entitySet = navigationSourceSegment?.NavigationSource as IEdmEntitySet;
- string operationId = null;
+ string? operationId = null;
if (secondLastSegment is ODataComplexPropertySegment complexSegment)
{
- string listOrGet = includeListOrGetPrefix ? (complexSegment.Property.Type.IsCollection() ? "List" : "Get") : null;
+ string? listOrGet = includeListOrGetPrefix ? (complexSegment.Property.Type.IsCollection() ? "List" : "Get") : null;
operationId = GenerateComplexPropertyPathOperationId(path, context, listOrGet);
}
else if (secondLastSegment is ODataNavigationPropertySegment navPropSegment)
{
- string prefix = null;
+ string? prefix = null;
if (includeListOrGetPrefix)
{
prefix = navPropSegment?.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many ? "List" : "Get";
@@ -391,22 +393,34 @@ internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path
else
{
string entityTypeName = keySegment.EntityType.Name;
- string getPrefix = includeListOrGetPrefix ? "Get" : null;
+ string? getPrefix = includeListOrGetPrefix ? "Get" : null;
string operationName = $"{getPrefix}{Utils.UpperFirstChar(entityTypeName)}";
if (keySegment.IsAlternateKey)
{
string alternateKeyName = string.Join("", keySegment.Identifier.Split(',').Select(static x => Utils.UpperFirstChar(x)));
operationName = $"{operationName}By{alternateKeyName}";
}
- operationId = (entitySet != null) ? entitySet.Name : singleton.Name;
+ if (entitySet != null)
+ {
+ operationId = entitySet.Name;
+ }
+ else if (singleton != null)
+ {
+ operationId = singleton.Name;
+ }
operationId += $".{entityTypeName}.{operationName}";
}
}
else if (secondLastSegment is ODataNavigationSourceSegment)
{
- operationId = (entitySet != null)
- ? entitySet.Name + "." + entitySet.EntityType.Name + $".{(includeListOrGetPrefix ? "List" : null)}" + Utils.UpperFirstChar(entitySet.EntityType.Name)
- : singleton.Name + "." + singleton.EntityType.Name + $".{(includeListOrGetPrefix ? "Get" : null)}" + Utils.UpperFirstChar(singleton.EntityType.Name);
+ if (entitySet != null)
+ {
+ operationId = entitySet.Name + "." + entitySet.EntityType.Name + $".{(includeListOrGetPrefix ? "List" : null)}" + Utils.UpperFirstChar(entitySet.EntityType.Name);
+ }
+ else if (singleton != null)
+ {
+ operationId = singleton.Name + "." + singleton.EntityType.Name + $".{(includeListOrGetPrefix ? "Get" : null)}" + Utils.UpperFirstChar(singleton.EntityType.Name);
+ }
}
return operationId;
@@ -419,7 +433,7 @@ internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path
/// Optional: The Edm model. Used for searching for the namespace alias.
/// The OpenAPI convert settings.
/// The element name, alias-prefixed or namespace-stripped if applicable.
- internal static string StripOrAliasNamespacePrefix(IEdmSchemaElement element, OpenApiConvertSettings settings, IEdmModel model = null)
+ internal static string StripOrAliasNamespacePrefix(IEdmSchemaElement element, OpenApiConvertSettings settings, IEdmModel? model = null)
{
Utils.CheckArgumentNull(element, nameof(element));
Utils.CheckArgumentNull(settings, nameof(settings));
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs
index 5d5e6ca7e..592100fe7 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs
@@ -24,7 +24,7 @@ internal static class OpenApiOperationExtensions
/// Optional: Whether to add a 204 no content response.
/// Optional: The OpenAPI schema of the response.
/// The OpenAPI document to lookup references.
- public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, OpenApiDocument document, bool addNoContent = false, IOpenApiSchema schema = null)
+ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, OpenApiDocument document, bool addNoContent = false, IOpenApiSchema? schema = null)
{
Utils.CheckArgumentNull(operation, nameof(operation));
Utils.CheckArgumentNull(settings, nameof(settings));
@@ -39,7 +39,7 @@ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiCon
{
if (settings.UseSuccessStatusCodeRange)
{
- OpenApiResponse response = null;
+ OpenApiResponse? response = null;
if (schema != null)
{
response = new()
@@ -57,22 +57,25 @@ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiCon
}
};
}
- operation.Responses.Add(Constants.StatusCodeClass2XX, response ?? Constants.StatusCodeClass2XX.GetResponse(document));
+ if ((response ?? Constants.StatusCodeClass2XX.GetResponse(document)) is {} x2xxResponse)
+ operation.Responses.Add(Constants.StatusCodeClass2XX, x2xxResponse);
}
- else
+ else if (Constants.StatusCode204.GetResponse(document) is {} x204Response)
{
- operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse(document));
+ operation.Responses.Add(Constants.StatusCode204, x204Response);
}
}
- if (settings.ErrorResponsesAsDefault)
+ if (settings.ErrorResponsesAsDefault && Constants.StatusCodeDefault.GetResponse(document) is {} defaultResponse)
{
- operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse(document));
+ operation.Responses.Add(Constants.StatusCodeDefault, defaultResponse);
}
else
{
- operation.Responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse(document));
- operation.Responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse(document));
+ if (Constants.StatusCodeClass4XX.GetResponse(document) is {} x4xxResponse)
+ operation.Responses.Add(Constants.StatusCodeClass4XX, x4xxResponse);
+ if (Constants.StatusCodeClass5XX.GetResponse(document) is {} x5xxResponse)
+ operation.Responses.Add(Constants.StatusCodeClass5XX, x5xxResponse);
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
index d5db7aa58..8f27b9d7b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
@@ -28,10 +28,10 @@ public static class Utils
///
/// The type of the term.
/// The qualified name.
- public static string GetTermQualifiedName()
+ public static string? GetTermQualifiedName()
{
object[] attributes = typeof(T).GetCustomAttributes(typeof(TermAttribute), false);
- if (attributes == null && attributes.Length == 0)
+ if (attributes == null || attributes.Length == 0)
{
return null;
}
@@ -45,7 +45,7 @@ public static string GetTermQualifiedName()
///
/// The input string.
/// The changed string.
- public static string UpperFirstChar(string input)
+ public static string? UpperFirstChar(string? input)
{
if (input == null)
{
@@ -129,7 +129,7 @@ internal static string ToFirstCharacterLowerCase(this string input)
///
/// The .
/// Optional: The navigation property name.
- internal static string NavigationPropertyPath(this ODataPath path, string navigationPropertyName = null)
+ internal static string NavigationPropertyPath(this ODataPath path, string? navigationPropertyName = null)
{
string value = string.Join("/",
path.Segments.OfType().Select(e => e.Identifier));
@@ -176,7 +176,7 @@ private static Dictionary GetCustomXMLAttributesValueMapping(IEd
{
Dictionary attributesValueMap = new();
- if ((!customXMLAttributesMapping?.Any() ?? true) ||
+ if (customXMLAttributesMapping is not {Count:>0} ||
model == null ||
element == null)
{
@@ -187,10 +187,10 @@ private static Dictionary GetCustomXMLAttributesValueMapping(IEd
{
string attributeName = item.Key.Split(':').Last(); // example, 'ags:IsHidden' --> 'IsHidden'
string extensionName = item.Value;
- EdmStringConstant customXMLAttribute = model.DirectValueAnnotationsManager.GetDirectValueAnnotations(element)?
+ var customXMLAttribute = model.DirectValueAnnotationsManager.GetDirectValueAnnotations(element)?
.Where(x => x.Name.Equals(attributeName, StringComparison.OrdinalIgnoreCase))?
.FirstOrDefault()?.Value as EdmStringConstant;
- string attributeValue = customXMLAttribute?.Value;
+ var attributeValue = customXMLAttribute?.Value;
if (!string.IsNullOrEmpty(attributeValue))
{
@@ -212,10 +212,10 @@ private static Dictionary GetCustomXMLAttributesValueMapping(IEd
internal static bool IsBaseTypeReferencedAsTypeInModel(
this IEdmModel model,
IEdmStructuredType baseType,
- IEnumerable structuredTypes = null,
- IEnumerable actions = null)
+ IEnumerable? structuredTypes = null,
+ IEnumerable? actions = null)
{
- string baseTypeName = baseType?.FullTypeName();
+ string baseTypeName = baseType.FullTypeName();
bool isBaseTypeEntity = Constants.EntityName.Equals(baseTypeName?.Split('.').Last(), StringComparison.OrdinalIgnoreCase);
if (!string.IsNullOrEmpty(baseTypeName) && !isBaseTypeEntity)
@@ -253,7 +253,7 @@ internal static bool IsBaseTypeReferencedAsTypeInModel(
///
/// The target .
/// The entity type of the target .
- internal static IEdmEntityType EntityTypeFromPathSegment(this ODataSegment segment)
+ internal static IEdmEntityType? EntityTypeFromPathSegment(this ODataSegment segment)
{
CheckArgumentNull(segment, nameof(segment));
@@ -279,12 +279,12 @@ internal static IEdmEntityType EntityTypeFromPathSegment(this ODataSegment segme
///
/// The target .
/// The entity type of the target .
- private static IEdmEntityType EntityTypeFromOperationSegment(this ODataSegment segment)
+ private static IEdmEntityType? EntityTypeFromOperationSegment(this ODataSegment segment)
{
CheckArgumentNull(segment, nameof(segment));
if (segment is ODataOperationSegment operationSegment &&
- operationSegment.Operation.Parameters.FirstOrDefault() is IEdmOperationParameter bindingParameter)
+ operationSegment.Operation?.Parameters.FirstOrDefault() is IEdmOperationParameter bindingParameter)
{
IEdmTypeReference bindingType = bindingParameter.Type;
@@ -339,10 +339,10 @@ internal static bool TryAddPath(this IDictionary pathI
}
ODataSegment lastSecondSegment = path.Segments.ElementAt(path.Count - secondLastSegmentIndex);
- IEdmEntityType boundEntityType = lastSecondSegment?.EntityTypeFromPathSegment();
+ var boundEntityType = lastSecondSegment?.EntityTypeFromPathSegment();
- IEdmEntityType operationEntityType = lastSegment.EntityTypeFromOperationSegment();
- IEnumerable derivedTypes = (operationEntityType != null)
+ var operationEntityType = lastSegment.EntityTypeFromOperationSegment();
+ var derivedTypes = (operationEntityType != null)
? context.Model.FindAllDerivedTypes(operationEntityType)
: null;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs
index 97ed1cb64..901079bef 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs
@@ -21,9 +21,9 @@ namespace Microsoft.OpenApi.OData.Edm
///
internal static class EdmVocabularyAnnotationExtensions
{
- private static IDictionary> _cachedAnnotations;
- private static IEdmModel _savedModel = null; // if diffenent model, the cache will be cleaned.
- private static object _objectLock = new object();
+ private static IDictionary>? _cachedAnnotations;
+ private static IEdmModel? _savedModel = null; // if different model, the cache will be cleaned.
+ private static readonly object _objectLock = new object();
///
/// Gets the boolean term value for the given .
@@ -54,8 +54,7 @@ internal static class EdmVocabularyAnnotationExtensions
// Note: Graph has a lot of annotations applied to the type, not to the navigation source.
// Here's a work around to retrieve these annotations from type if we can't find it from navigation source.
// It's the same reason for belows
- IEdmNavigationSource navigationSource = target as IEdmNavigationSource;
- if (navigationSource != null)
+ if (target is IEdmNavigationSource navigationSource)
{
IEdmEntityType entityType = navigationSource.EntityType;
value = model.GetBoolean(entityType, term);
@@ -87,7 +86,7 @@ internal static class EdmVocabularyAnnotationExtensions
/// The Edm target.
/// The Term qualified name.
/// Null or the string value for this annotation.
- public static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
+ public static string? GetString(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(target, nameof(target));
@@ -95,7 +94,7 @@ public static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable t
return GetOrAddCached(model, target, qualifiedName, () =>
{
- string value = null;
+ string? value = null;
IEdmTerm term = model.FindTerm(qualifiedName);
if (term != null)
{
@@ -106,8 +105,7 @@ public static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable t
}
else
{
- IEdmNavigationSource navigationSource = target as IEdmNavigationSource;
- if (navigationSource != null)
+ if (target is IEdmNavigationSource navigationSource)
{
IEdmEntityType entityType = navigationSource.EntityType;
value = model.GetString(entityType, term);
@@ -127,11 +125,10 @@ public static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable t
/// The Edm model.
/// The target element.
/// Null or the record value (a complex type) for this annotation.
- public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target)
- where T : IRecord, new()
+ public static T? GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target)
+ where T : class, IRecord, new()
{
- string qualifiedName = Utils.GetTermQualifiedName();
- return model.GetRecord(target, qualifiedName);
+ return Utils.GetTermQualifiedName() is string qualifiedName ? model.GetRecord(target, qualifiedName) : null;
}
///
@@ -142,8 +139,8 @@ public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable tar
/// The Edm target.
/// The Term qualified name.
/// Null or the record value (a complex type) for this annotation.
- public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
- where T : IRecord, new()
+ public static T? GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
+ where T : class, IRecord, new()
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(target, nameof(target));
@@ -151,7 +148,7 @@ public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable tar
return GetOrAddCached(model, target, qualifiedName, () =>
{
- T value = default;
+ T? value = default;
IEdmTerm term = model.FindTerm(qualifiedName);
if (term != null)
{
@@ -162,8 +159,7 @@ public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable tar
}
else
{
- IEdmNavigationSource navigationSource = target as IEdmNavigationSource;
- if (navigationSource != null)
+ if (target is IEdmNavigationSource navigationSource)
{
IEdmEntityType entityType = navigationSource.EntityType;
value = model.GetRecord(entityType, term);
@@ -183,8 +179,8 @@ public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable tar
/// The string representation of the Edm target path.
/// The Term qualified name.
///
- public static T GetRecord(this IEdmModel model, string targetPath, string qualifiedName)
- where T : IRecord, new()
+ public static T? GetRecord(this IEdmModel model, string targetPath, string qualifiedName)
+ where T : class, IRecord, new()
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -204,7 +200,7 @@ public static T GetRecord(this IEdmModel model, string targetPath, string qua
/// The Edm target.
/// The Term qualified name.
/// Null or the collection of string value for this annotation.
- public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
+ public static IEnumerable? GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(target, nameof(target));
@@ -212,7 +208,7 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabu
return GetOrAddCached(model, target, qualifiedName, () =>
{
- IEnumerable value = null;
+ IEnumerable? value = null;
IEdmTerm term = model.FindTerm(qualifiedName);
if (term != null)
{
@@ -223,8 +219,7 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabu
}
else
{
- IEdmNavigationSource navigationSource = target as IEdmNavigationSource;
- if (navigationSource != null)
+ if (target is IEdmNavigationSource navigationSource)
{
IEdmEntityType entityType = navigationSource.EntityType;
value = model.GetCollection(entityType, term);
@@ -244,11 +239,10 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabu
/// The Edm model.
/// The Edm target.
/// Null or the colllection of record value (a complex type) for this annotation.
- public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target)
+ public static IEnumerable? GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target)
where T : IRecord, new()
{
- string qualifiedName = Utils.GetTermQualifiedName();
- return GetCollection(model, target, qualifiedName);
+ return Utils.GetTermQualifiedName() is string qualifiedName ? GetCollection(model, target, qualifiedName) : null;
}
///
@@ -259,7 +253,7 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabula
/// The Edm target.
/// The Term qualified name.
/// Null or the colllection of record value (a complex type) for this annotation.
- public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
+ public static IEnumerable? GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
where T : IRecord, new()
{
Utils.CheckArgumentNull(model, nameof(model));
@@ -268,7 +262,7 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabula
return GetOrAddCached(model, target, qualifiedName, () =>
{
- IEnumerable value = null;
+ IEnumerable? value = null;
IEdmTerm term = model.FindTerm(qualifiedName);
if (term != null)
{
@@ -279,8 +273,7 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabula
}
else
{
- IEdmNavigationSource navigationSource = target as IEdmNavigationSource;
- if (navigationSource != null)
+ if (target is IEdmNavigationSource navigationSource)
{
IEdmEntityType entityType = navigationSource.EntityType;
value = model.GetCollection(entityType, term);
@@ -299,10 +292,11 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabula
/// The Edm target.
/// The link relation type for path operation.
/// Null or the links record value (a complex type) for this annotation.
- public static LinkType GetLinkRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, string linkRel)
+ public static LinkType? GetLinkRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, string linkRel)
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(target, nameof(target));
+ Utils.CheckArgumentNull(linkRel, nameof(linkRel));
return model.GetCollection(target, CoreConstants.Links)?.FirstOrDefault(x => x.Rel == linkRel);
}
@@ -314,7 +308,7 @@ public static LinkType GetLinkRecord(this IEdmModel model, IEdmVocabularyAnnotat
/// The string representation of the Edm target path.
/// The link relation type for path operation.
/// Null or the links record value (a complex type) for this annotation.
- public static LinkType GetLinkRecord(this IEdmModel model, string targetPath, string linkRel)
+ public static LinkType? GetLinkRecord(this IEdmModel model, string targetPath, string linkRel)
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -332,7 +326,7 @@ public static LinkType GetLinkRecord(this IEdmModel model, string targetPath, st
/// The Edm model.
/// The Edm target.
/// The created object.
- public static IEnumerable GetAuthorizations(this IEdmModel model, IEdmVocabularyAnnotatable target)
+ public static IEnumerable? GetAuthorizations(this IEdmModel model, IEdmVocabularyAnnotatable target)
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(target, nameof(target));
@@ -342,7 +336,7 @@ public static IEnumerable GetAuthorizations(this IEdmModel model,
IEdmTerm term = model.FindTerm(AuthorizationConstants.Authorizations);
if (term != null)
{
- IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
+ IEdmVocabularyAnnotation? annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection)
{
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
@@ -353,9 +347,8 @@ public static IEnumerable GetAuthorizations(this IEdmModel model,
Debug.Assert(e.ExpressionKind == EdmExpressionKind.Record);
IEdmRecordExpression recordExpression = (IEdmRecordExpression)e;
- Authorization auth = Authorization.CreateAuthorization(recordExpression);
- return auth;
- });
+ return Authorization.CreateAuthorization(recordExpression);
+ }).OfType();
}
}
}
@@ -364,7 +357,7 @@ public static IEnumerable GetAuthorizations(this IEdmModel model,
});
}
- public static string GetDescriptionAnnotation(this IEdmModel model, string targetPath)
+ public static string? GetDescriptionAnnotation(this IEdmModel model, string targetPath)
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -376,7 +369,7 @@ public static string GetDescriptionAnnotation(this IEdmModel model, string targe
return model.GetDescriptionAnnotation(target);
}
- private static T GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName, Func createFunc)
+ private static T? GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName, Func createFunc)
{
if (model == null || target == null)
{
@@ -400,8 +393,8 @@ private static T GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatab
_cachedAnnotations = new Dictionary>();
}
- object restriction;
- if (_cachedAnnotations.TryGetValue(target, out IDictionary value))
+ object? restriction;
+ if (_cachedAnnotations.TryGetValue(target, out var value))
{
// Here means we visited target before and we are sure that the value is not null.
if (value.TryGetValue(qualifiedName, out restriction))
@@ -409,9 +402,8 @@ private static T GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatab
T ret = (T)restriction;
return ret;
}
- else
+ else if (createFunc() is T ret)
{
- T ret = createFunc();
value[qualifiedName] = ret;
return ret;
}
@@ -420,9 +412,12 @@ private static T GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatab
// It's first time to query this target, create new dictionary and restriction.
value = new Dictionary();
_cachedAnnotations[target] = value;
- T newAnnotation = createFunc();
- value[qualifiedName] = newAnnotation;
- return newAnnotation;
+ if (createFunc() is T newAnnotation)
+ {
+ value[qualifiedName] = newAnnotation;
+ return newAnnotation;
+ }
+ return default;
}
}
@@ -432,7 +427,7 @@ private static T GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatab
Debug.Assert(target != null);
Debug.Assert(term != null);
- IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
+ IEdmVocabularyAnnotation? annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.BooleanConstant)
{
IEdmBooleanConstantExpression boolConstant = (IEdmBooleanConstantExpression)annotation.Value;
@@ -445,13 +440,13 @@ private static T GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatab
return null;
}
- private static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
+ private static string? GetString(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
{
Debug.Assert(model != null);
Debug.Assert(target != null);
Debug.Assert(term != null);
- IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
+ IEdmVocabularyAnnotation? annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.StringConstant)
{
IEdmStringConstantExpression stringConstant = (IEdmStringConstantExpression)annotation.Value;
@@ -461,13 +456,13 @@ private static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable
return null;
}
- private static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
+ private static IEnumerable? GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
{
Debug.Assert(model != null);
Debug.Assert(target != null);
Debug.Assert(term != null);
- IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
+ IEdmVocabularyAnnotation? annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection)
{
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
@@ -480,14 +475,14 @@ private static IEnumerable GetCollection(this IEdmModel model, IEdmVocab
return null;
}
- private static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
+ private static T? GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
where T : IRecord, new()
{
Debug.Assert(model != null);
Debug.Assert(target != null);
Debug.Assert(term != null);
- IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
+ IEdmVocabularyAnnotation? annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Record)
{
IEdmRecordExpression recordExpression = (IEdmRecordExpression)annotation.Value;
@@ -499,14 +494,14 @@ private static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable ta
return default;
}
- private static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
+ private static IEnumerable? GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
where T : IRecord, new()
{
Debug.Assert(model != null);
Debug.Assert(target != null);
Debug.Assert(term != null);
- IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
+ IEdmVocabularyAnnotation? annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault();
if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection)
{
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
index 3ece9f1f6..6c3650578 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
@@ -48,7 +48,7 @@ private static bool IsUrlEscapeFunction(this IEdmModel model, IEdmFunction funct
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(function, nameof(function));
- IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(function,
+ var annotation = model.FindVocabularyAnnotations(function,
CommunityVocabularyModel.UrlEscapeFunctionTerm).FirstOrDefault();
if (annotation != null)
{
@@ -58,12 +58,11 @@ private static bool IsUrlEscapeFunction(this IEdmModel model, IEdmFunction funct
return true;
}
- IEdmBooleanConstantExpression tagConstant = annotation.Value as IEdmBooleanConstantExpression;
- if (tagConstant != null)
- {
- return tagConstant.Value;
- }
- }
+ if (annotation.Value is IEdmBooleanConstantExpression tagConstant)
+ {
+ return tagConstant.Value;
+ }
+ }
return false;
}
@@ -73,16 +72,16 @@ private static bool IsUrlEscapeFunction(this IEdmModel model, IEdmFunction funct
///
/// The Edm model.
/// The dictionary.
- public static IDictionary> LoadAllNavigationSources(this IEdmModel model)
+ public static Dictionary> LoadAllNavigationSources(this IEdmModel model)
{
var navigationSourceDic = new Dictionary>();
if (model != null && model.EntityContainer != null)
{
Action>> action = (ns, dic) =>
{
- if (!dic.TryGetValue(ns.EntityType, out IList value))
+ if (!dic.TryGetValue(ns.EntityType, out var value))
{
- value = new List();
+ value = [];
dic[ns.EntityType] = value;
}
@@ -96,9 +95,9 @@ public static IDictionary> LoadAllNa
}
// singleton
- foreach (var singelton in model.EntityContainer.Singletons())
+ foreach (var singleton in model.EntityContainer.Singletons())
{
- action(singelton, navigationSourceDic);
+ action(singleton, navigationSourceDic);
}
}
@@ -114,7 +113,7 @@ public static IEnumerable FindAllBaseTypes(this IEdmEntityType e
{
if (entityType == null)
{
- yield return null;
+ yield break;
}
IEdmEntityType current = entityType.BaseEntityType();
@@ -134,7 +133,7 @@ public static IEnumerable FindAllBaseTypes(this IEdmComplexType
{
if (complexType == null)
{
- yield return null;
+ yield break;
}
IEdmComplexType current = complexType.BaseComplexType();
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmOperationProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmOperationProvider.cs
index fd928476a..d62a24c24 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmOperationProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmOperationProvider.cs
@@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.OData.Edm
{
internal class EdmOperationProvider
{
- private Lazy>> _boundEdmOperations;
+ private readonly Lazy>> _boundEdmOperations;
///
/// Gets the Edm model.
@@ -31,7 +31,7 @@ public EdmOperationProvider(IEdmModel model)
Model = model;
_boundEdmOperations = new Lazy>>(
- () => LoadEdmOperations(), isThreadSafe: false);
+ LoadEdmOperations, isThreadSafe: false);
}
public IDictionary> Operations => _boundEdmOperations.Value;
@@ -42,20 +42,19 @@ public EdmOperationProvider(IEdmModel model)
/// The binding entity type.
/// The collection or not.
/// The found Edm operations.
- public IEnumerable FindOperations(IEdmEntityType entityType, bool collection)
+ public IEnumerable? FindOperations(IEdmEntityType entityType, bool collection)
{
Utils.CheckArgumentNull(entityType, nameof(entityType));
string fullTypeName = collection ? "Collection(" + entityType.FullName() + ")" : entityType.FullName();
- IList edmOperations;
- _boundEdmOperations.Value.TryGetValue(fullTypeName, out edmOperations);
+ if (!_boundEdmOperations.Value.TryGetValue(fullTypeName, out var edmOperations)) return null;
foreach (IEdmEntityType derived in Model.FindAllDerivedTypes(entityType).OfType())
{
string subFullTypeName = collection ? "Collection(" + derived.FullName() + ")" : derived.FullName();
- if (_boundEdmOperations.Value.TryGetValue(subFullTypeName, out IList edmSubOperations))
+ if (_boundEdmOperations.Value.TryGetValue(subFullTypeName, out var edmSubOperations))
{
foreach(var edmOperation in edmSubOperations)
{
@@ -77,9 +76,9 @@ private IDictionary> LoadEdmOperations()
string bindingTypeName = bindingParameter.Type.FullName();
- if (!edmOperationDict.TryGetValue(bindingTypeName, out IList value))
+ if (!edmOperationDict.TryGetValue(bindingTypeName, out var value))
{
- value = new List();
+ value = [];
edmOperationDict[bindingTypeName] = value;
}
value.Add(edmOperation);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataComplexPropertySegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataComplexPropertySegment.cs
index 5c74f5b1e..904935fdd 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataComplexPropertySegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataComplexPropertySegment.cs
@@ -26,7 +26,7 @@ public ODataComplexPropertySegment(IEdmStructuralProperty property)
}
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.ComplexProperty;
@@ -42,13 +42,13 @@ public ODataComplexPropertySegment(IEdmStructuralProperty property)
///
/// Gets the type definition of the property this segment was inserted for.
///
- public IEdmComplexType ComplexType =>
+ public IEdmComplexType? ComplexType =>
(Property.Type.IsCollection() ? Property.Type.Definition.AsElementType() : Property.Type.AsComplex().Definition) as IEdmComplexType;
///
public override IEnumerable GetAnnotables()
{
- return new IEdmVocabularyAnnotatable[] { Property, ComplexType }.Union(ComplexType.FindAllBaseTypes());
+ return new IEdmVocabularyAnnotatable[] { Property }.Union(ComplexType is null ? [] : [ComplexType]).Union(ComplexType?.FindAllBaseTypes() ?? []);
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
index 300accc9f..1441a32fd 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
@@ -9,6 +9,7 @@
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Generator;
@@ -24,7 +25,7 @@ namespace Microsoft.OpenApi.OData.Edm
///
internal class ODataContext
{
- private IEnumerable _allPaths;
+ private IEnumerable? _allPaths;
private readonly IODataPathProvider _pathProvider;
///
@@ -135,7 +136,7 @@ public IEnumerable AllPaths
///
/// Gets all tags.
///
- public ISet Tags { get; private set; }
+ public ISet? Tags { get; private set; }
///
/// Append tag.
@@ -145,7 +146,7 @@ internal void AppendTag(OpenApiTag tagItem)
{
Tags ??= new HashSet();
- if (FindTagByName(tagItem.Name) is not null)
+ if (tagItem.Name is not null && FindTagByName(tagItem.Name) is not null)
{
return;
}
@@ -158,7 +159,7 @@ internal void AppendTag(OpenApiTag tagItem)
///
/// The name to lookup the tag.
///
- internal OpenApiTag FindTagByName(string name)
+ internal OpenApiTag? FindTagByName(string name)
{
Utils.CheckArgumentNullOrEmpty(name, nameof(name));
return Tags?.FirstOrDefault(t => StringComparer.Ordinal.Equals(t.Name, name));
@@ -180,11 +181,13 @@ internal void AddExtensionToTag(string tagName, string extensionName, OpenApiAny
if (FindTagByName(tagName) is {} foundTag)
{
+ foundTag.Extensions ??= new Dictionary();
foundTag.Extensions.TryAdd(extensionName, extensionValue);
}
else
{
var tag = initialValueFactory();
+ tag.Extensions ??= new Dictionary();
tag.Extensions.TryAdd(extensionName, extensionValue);
AppendTag(tag);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataDollarCountSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataDollarCountSegment.cs
index ac0a04d27..841df8cd3 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataDollarCountSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataDollarCountSegment.cs
@@ -17,10 +17,10 @@ public class ODataDollarCountSegment : ODataSegment
///
/// Get the static instance of $count segment.
///
- internal static ODataDollarCountSegment Instance = new();
+ internal static readonly ODataDollarCountSegment Instance = new();
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.DollarCount;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs
index 3af32c2fa..748b5b811 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs
@@ -45,7 +45,7 @@ public ODataKeySegment(IEdmEntityType entityType, IDictionary ke
///
/// Gets the key/template mappings.
///
- public IDictionary KeyMappings { get; }
+ public IDictionary? KeyMappings { get; }
///
public override IEdmEntityType EntityType { get; }
@@ -59,7 +59,7 @@ public override string Identifier
get
{
IList keys = IsAlternateKey ?
- KeyMappings.Values.ToList() :
+ KeyMappings?.Values.ToList() ?? [] :
EntityType.Key().Select(static x => x.Name).ToList();
return string.Join(",", keys);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataMetadataSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataMetadataSegment.cs
index 859c30dec..ab28b7668 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataMetadataSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataMetadataSegment.cs
@@ -16,7 +16,7 @@ namespace Microsoft.OpenApi.OData.Edm
public class ODataMetadataSegment : ODataSegment
{
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.Metadata;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationPropertySegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationPropertySegment.cs
index 69ea6f562..6c725f58f 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationPropertySegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationPropertySegment.cs
@@ -42,7 +42,7 @@ public ODataNavigationPropertySegment(IEdmNavigationProperty navigationProperty)
///
public override IEnumerable GetAnnotables()
{
- return new IEdmVocabularyAnnotatable[] { NavigationProperty, EntityType }.Union(EntityType.FindAllBaseTypes());
+ return new IEdmVocabularyAnnotatable[] { NavigationProperty, EntityType }.Union(EntityType.FindAllBaseTypes() ?? []);
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationSourceSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationSourceSegment.cs
index 8981af686..a4143d504 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationSourceSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataNavigationSourceSegment.cs
@@ -42,7 +42,9 @@ public ODataNavigationSourceSegment(IEdmNavigationSource navigationSource)
///
public override IEnumerable GetAnnotables()
{
- return new IEdmVocabularyAnnotatable[] { NavigationSource as IEdmVocabularyAnnotatable, EntityType }.Union(EntityType.FindAllBaseTypes());
+ return (NavigationSource is IEdmVocabularyAnnotatable source ? new IEdmVocabularyAnnotatable[]{source} : [])
+ .Union([EntityType])
+ .Union(EntityType.FindAllBaseTypes());
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs
index 4a8ebd51f..ee2b70df0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs
@@ -41,7 +41,7 @@ public ODataOperationImportSegment(IEdmOperationImport operationImport, IDiction
///
/// Gets the parameter mappings.
///
- public IDictionary ParameterMappings { get; }
+ public IDictionary? ParameterMappings { get; }
///
/// Gets the operation import.
@@ -49,7 +49,7 @@ public ODataOperationImportSegment(IEdmOperationImport operationImport, IDiction
public IEdmOperationImport OperationImport { get; }
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.OperationImport;
@@ -60,7 +60,7 @@ public ODataOperationImportSegment(IEdmOperationImport operationImport, IDiction
///
public override IEnumerable GetAnnotables()
{
- return new IEdmVocabularyAnnotatable[] { OperationImport };
+ return [OperationImport];
}
///
@@ -68,15 +68,15 @@ public override string GetPathItemName(OpenApiConvertSettings settings, HashSet<
{
Utils.CheckArgumentNull(settings, nameof(settings));
- if (OperationImport.IsFunctionImport())
+ if (OperationImport.IsFunctionImport() && OperationImport is IEdmFunctionImport edmFunctionImport)
{
- return FunctionImportName(OperationImport as IEdmFunctionImport, settings, parameters);
+ return FunctionImportName(edmFunctionImport, settings, parameters);
}
return OperationImport.Name;
}
- private string FunctionImportName(IEdmFunctionImport functionImport, OpenApiConvertSettings settings, HashSet parameters)
+ private static string FunctionImportName(IEdmFunctionImport functionImport, OpenApiConvertSettings settings, HashSet parameters)
{
StringBuilder functionName = new StringBuilder(functionImport.Name);
functionName.Append("(");
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs
index 6ad4a2b5b..fabee69ce 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs
@@ -72,17 +72,17 @@ public ODataOperationSegment(IEdmOperation operation, bool isEscapedFunction, IE
_model = model ?? throw Error.ArgumentNull(nameof(model));
}
- private readonly IEdmModel _model;
+ private readonly IEdmModel? _model;
///
/// Gets the parameter mappings.
///
- public IDictionary ParameterMappings { get; }
+ public IDictionary? ParameterMappings { get; }
///
/// Gets the operation.
///
- public IEdmOperation Operation { get; }
+ public IEdmOperation? Operation { get; }
///
/// Gets the is escaped function.
@@ -93,31 +93,30 @@ public ODataOperationSegment(IEdmOperation operation, bool isEscapedFunction, IE
public override ODataSegmentKind Kind => ODataSegmentKind.Operation;
///
- public override string Identifier { get => Operation.Name; }
+ public override string? Identifier { get => Operation?.Name; }
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
- public override string GetPathItemName(OpenApiConvertSettings settings, HashSet parameters)
+ public override string? GetPathItemName(OpenApiConvertSettings settings, HashSet parameters)
{
Utils.CheckArgumentNull(settings, nameof(settings));
- if (Operation.IsFunction())
+ if (Operation is IEdmFunction function)
{
- return FunctionName(Operation as IEdmFunction, settings, parameters);
+ return FunctionName(function, settings, parameters);
}
- return OperationName(Operation, settings);
+ return Operation is null ? null : OperationName(Operation, settings);
}
internal IDictionary GetNameMapping(OpenApiConvertSettings settings, HashSet parameters)
{
IDictionary parameterNamesMapping = new Dictionary();
- if (Operation.IsFunction())
+ if (Operation is IEdmFunction function)
{
- IEdmFunction function = Operation as IEdmFunction;
if (settings.EnableUriEscapeFunctionCall && IsEscapedFunction)
{
string parameterName = function.Parameters.Last().Name;
@@ -156,8 +155,6 @@ private string FunctionName(IEdmFunction function, OpenApiConvertSettings settin
{
if (settings.EnableUriEscapeFunctionCall && IsEscapedFunction)
{
- // Debug.Assert(function.Parameters.Count == 2); It should be verify at Edm model.
- // Debug.Assert(function.IsBound == true);
string parameterName = function.Parameters.Last().Name;
string uniqueName = Utils.GetUniqueName(parameterName, parameters);
if (function.IsComposable)
@@ -172,7 +169,7 @@ private string FunctionName(IEdmFunction function, OpenApiConvertSettings settin
StringBuilder functionName = new();
functionName.Append(OperationName(function, settings));
- functionName.Append("(");
+ functionName.Append('(');
int skip = function.IsBound ? 1 : 0;
functionName.Append(string.Join(",", function.Parameters.Skip(skip).Select(p =>
@@ -184,7 +181,7 @@ private string FunctionName(IEdmFunction function, OpenApiConvertSettings settin
: p.Name + $"={quote}{{{uniqueName}}}{quote}";
})));
- functionName.Append(")");
+ functionName.Append(')');
return functionName.ToString();
}
@@ -192,7 +189,7 @@ private string FunctionName(IEdmFunction function, OpenApiConvertSettings settin
///
public override IEnumerable GetAnnotables()
{
- return new IEdmVocabularyAnnotatable[] { Operation };
+ return Operation is null ? [] : [Operation];
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs
index e3a28619c..5ae52b2fa 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs
@@ -20,7 +20,7 @@ namespace Microsoft.OpenApi.OData.Edm
public class ODataPath : IEnumerable, IComparable
{
private ODataPathKind? _pathKind;
- private string _defaultPathItemName;
+ private string? _defaultPathItemName;
///
/// Initializes a new instance of class.
@@ -54,7 +54,7 @@ public ODataPath(params ODataSegment[] segments)
/// Gets/Sets the path template for this path.
/// If it is set, it will be used to generate the path item.
///
- public string PathTemplate { get; set; }
+ public string? PathTemplate { get; set; }
///
/// Gets the segments.
@@ -80,12 +80,12 @@ public virtual ODataPathKind Kind
///
/// Gets the first segment in the path. Returns null if the path is empty.
///
- public ODataSegment FirstSegment => Segments.Count == 0 ? null : Segments[0];
+ public ODataSegment? FirstSegment => Segments is null || Segments.Count == 0 ? null : Segments[0];
///
/// Get the last segment in the path. Returns null if the path is empty.
///
- public ODataSegment LastSegment => Segments.Count == 0 ? null : this.Segments[Segments.Count - 1];
+ public ODataSegment? LastSegment => Segments is null || Segments.Count == 0 ? null : this.Segments[Segments.Count - 1];
///
/// Get the number of segments in this path.
@@ -150,35 +150,34 @@ public string GetPathItemName(OpenApiConvertSettings settings)
if (!string.IsNullOrWhiteSpace(settings.PathPrefix))
{
- sb.Append("/");
+ sb.Append('/');
sb.Append(settings.PathPrefix);
}
foreach (var segment in Segments)
{
- string pathItemName = segment.GetPathItemName(settings, parameters);
+ var pathItemName = segment.GetPathItemName(settings, parameters);
if (segment is ODataKeySegment keySegment &&
(settings.EnableKeyAsSegment == null || !settings.EnableKeyAsSegment.Value || keySegment.IsAlternateKey))
{
- sb.Append("(");
+ sb.Append('(');
sb.Append(pathItemName);
- sb.Append(")");
+ sb.Append(')');
}
else // other segments
{
- if (segment.Kind == ODataSegmentKind.Operation)
+ if (segment.Kind == ODataSegmentKind.Operation &&
+ segment is ODataOperationSegment operation &&
+ operation.IsEscapedFunction &&
+ settings.EnableUriEscapeFunctionCall)
{
- ODataOperationSegment operation = (ODataOperationSegment)segment;
- if (operation.IsEscapedFunction && settings.EnableUriEscapeFunctionCall)
- {
- sb.Append(":/");
- sb.Append(pathItemName);
- continue;
- }
+ sb.Append(":/");
+ sb.Append(pathItemName);
+ continue;
}
- sb.Append("/");
+ sb.Append('/');
sb.Append(pathItemName);
}
}
@@ -204,10 +203,7 @@ internal bool SupportHttpMethod(string method)
/// The whole path object.
internal ODataPath Push(ODataSegment segment)
{
- if (Segments == null)
- {
- Segments = new List();
- }
+ Segments ??= [];
_pathKind = null;
_defaultPathItemName = null;
@@ -290,7 +286,7 @@ public override string ToString()
return PathTemplate;
}
- return "/" + String.Join("/", Segments.Select(e => e.Kind));
+ return "/" + string.Join("/", Segments.Select(e => e.Kind));
}
///
@@ -298,9 +294,9 @@ public override string ToString()
///
/// The compare to ODataPath.
/// true/false
- public int CompareTo(ODataPath other)
+ public int CompareTo(ODataPath? other)
{
- return GetPathItemName().CompareTo(other.GetPathItemName());
+ return GetPathItemName().CompareTo(other?.GetPathItemName());
}
private ODataPathKind CalcPathType()
@@ -365,7 +361,7 @@ private ODataPathKind CalcPathType()
///
/// The settings.
///The suffix.
- public string GetPathHash(OpenApiConvertSettings settings) =>
- LastSegment.GetPathHash(settings, this);
+ public string? GetPathHash(OpenApiConvertSettings settings) =>
+ LastSegment?.GetPathHash(settings, this);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs
index d9275aebc..c2d5c79d9 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs
@@ -19,17 +19,17 @@ namespace Microsoft.OpenApi.OData.Edm
///
public class ODataPathProvider : IODataPathProvider
{
- private IDictionary> _allNavigationSources;
+ private Dictionary>? _allNavigationSources;
- private IDictionary> _allNavigationSourcePaths =
+ private readonly IDictionary> _allNavigationSourcePaths =
new Dictionary>();
- private IDictionary> _allNavigationPropertyPaths =
+ private readonly IDictionary> _allNavigationPropertyPaths =
new Dictionary>();
- private IList _allOperationPaths = new List();
+ private readonly List _allOperationPaths = [];
- private IEdmModel _model;
+ private IEdmModel? _model;
private readonly IDictionary> _dollarCountPaths =
new Dictionary>();
@@ -52,39 +52,45 @@ public virtual IEnumerable GetPaths(IEdmModel model, OpenApiConvertSe
{
if (model == null || model.EntityContainer == null)
{
- return Enumerable.Empty();
+ return [];
}
Initialize(model);
- // entity set
- foreach (IEdmEntitySet entitySet in _model.EntityContainer.EntitySets())
+ if (_model is not null)
{
- if (CanFilter(entitySet))
- {
- RetrieveNavigationSourcePaths(entitySet, settings);
- }
- }
+ // entity set
+ foreach (var entitySet in _model.EntityContainer.EntitySets())
+ {
+ if (CanFilter(entitySet))
+ {
+ RetrieveNavigationSourcePaths(entitySet, settings);
+ }
+ }
- // singleton
- foreach (IEdmSingleton singleton in _model.EntityContainer.Singletons())
- {
- if (CanFilter(singleton))
- {
- RetrieveNavigationSourcePaths(singleton, settings);
- }
+ // singleton
+ foreach (var singleton in _model.EntityContainer.Singletons())
+ {
+ if (CanFilter(singleton))
+ {
+ RetrieveNavigationSourcePaths(singleton, settings);
+ }
+ }
}
// bound operations
RetrieveBoundOperationPaths(settings);
- // unbound operations
- foreach (IEdmOperationImport import in _model.EntityContainer.OperationImports())
+ if (_model is not null)
{
- if (CanFilter(import))
- {
- AppendPath(new ODataPath(new ODataOperationImportSegment(import)));
- }
+ // unbound operations
+ foreach (IEdmOperationImport import in _model.EntityContainer.OperationImports())
+ {
+ if (CanFilter(import))
+ {
+ AppendPath(new ODataPath(new ODataOperationImportSegment(import)));
+ }
+ }
}
return MergePaths();
@@ -142,9 +148,9 @@ private void AppendPath(ODataPath path)
case ODataPathKind.MediaEntity:
if (path.FirstSegment is ODataNavigationSourceSegment navigationSourceSegment)
{
- if(!_allNavigationSourcePaths.TryGetValue(navigationSourceSegment.EntityType, out IList nsList))
+ if(!_allNavigationSourcePaths.TryGetValue(navigationSourceSegment.EntityType, out var nsList))
{
- nsList = new List();
+ nsList = [];
_allNavigationSourcePaths[navigationSourceSegment.EntityType] = nsList;
}
@@ -157,9 +163,9 @@ private void AppendPath(ODataPath path)
}
else
{
- if (!_dollarCountPaths.TryGetValue(navigationSourceSegment.EntityType, out IList dollarPathList))
+ if (!_dollarCountPaths.TryGetValue(navigationSourceSegment.EntityType, out var dollarPathList))
{
- dollarPathList = new List();
+ dollarPathList = [];
_dollarCountPaths[navigationSourceSegment.EntityType] = dollarPathList;
}
dollarPathList.Add(path);
@@ -174,9 +180,9 @@ private void AppendPath(ODataPath path)
case ODataPathKind.Ref:
ODataNavigationPropertySegment navigationPropertySegment = path.OfType().Last();
- if (!_allNavigationPropertyPaths.TryGetValue(navigationPropertySegment.EntityType, out IList npList))
+ if (!_allNavigationPropertyPaths.TryGetValue(navigationPropertySegment.EntityType, out var npList))
{
- npList = new List();
+ npList = [];
_allNavigationPropertyPaths[navigationPropertySegment.EntityType] = npList;
}
@@ -190,7 +196,7 @@ private void AppendPath(ODataPath path)
foreach (var kvp in _dollarCountPaths)
{
if (kvp.Value.FirstOrDefault(p => DollarCountAndOperationPathsSimilar(p, path)) is ODataPath dollarCountPath &&
- _allNavigationSourcePaths.TryGetValue(kvp.Key, out IList dollarPathList))
+ _allNavigationSourcePaths.TryGetValue(kvp.Key, out var dollarPathList))
{
dollarPathList.Remove(dollarCountPath);
break;
@@ -208,9 +214,9 @@ private void AppendPath(ODataPath path)
bool DollarCountAndOperationPathsSimilar(ODataPath path1, ODataPath path2)
{
if ((path1.Kind == ODataPathKind.DollarCount &&
- path2.Kind == ODataPathKind.Operation && path2.LastSegment.Identifier.Equals(Constants.CountSegmentIdentifier, StringComparison.OrdinalIgnoreCase)) ||
+ path2.Kind == ODataPathKind.Operation && Constants.CountSegmentIdentifier.Equals(path2.LastSegment?.Identifier, StringComparison.OrdinalIgnoreCase)) ||
(path2.Kind == ODataPathKind.DollarCount &&
- path1.Kind == ODataPathKind.Operation && path1.LastSegment.Identifier.Equals(Constants.CountSegmentIdentifier, StringComparison.OrdinalIgnoreCase)))
+ path1.Kind == ODataPathKind.Operation && Constants.CountSegmentIdentifier.Equals(path1.LastSegment?.Identifier, StringComparison.OrdinalIgnoreCase)))
{
return GetModifiedPathItemName(path1)?.Equals(GetModifiedPathItemName(path2), StringComparison.OrdinalIgnoreCase) ?? false;
}
@@ -218,9 +224,9 @@ bool DollarCountAndOperationPathsSimilar(ODataPath path1, ODataPath path2)
return false;
}
- string GetModifiedPathItemName(ODataPath path)
+ string? GetModifiedPathItemName(ODataPath path)
{
- if (!path.Any()) return null;
+ if (path.Count == 0) return null;
IEnumerable modifiedSegments = path.Take(path.Count - 1);
ODataPath modifiedPath = new(modifiedSegments);
@@ -242,14 +248,15 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource
ODataPath path = new(new ODataNavigationSourceSegment(navigationSource));
AppendPath(path.Clone());
- IEdmEntitySet entitySet = navigationSource as IEdmEntitySet;
IEdmEntityType entityType = navigationSource.EntityType;
- CountRestrictionsType count = null;
+ CountRestrictionsType? count = null;
bool? indexableByKey = false;
+ var entitySetIsNull = true;
// for entity set, create a path with key and a $count path
- if (entitySet != null)
+ if (navigationSource is IEdmEntitySet entitySet && _model is not null)
{
+ entitySetIsNull = false;
string targetPath = path.GetTargetPath(_model);
count = _model.GetRecord(targetPath, CapabilitiesConstants.CountRestrictions)
?? _model.GetRecord(entitySet, CapabilitiesConstants.CountRestrictions);
@@ -291,13 +298,13 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource
}
}
- if (entitySet != null && (indexableByKey ?? true))
+ if (!entitySetIsNull && (indexableByKey ?? true))
{
path.Pop(); // end of entity
}
path.Pop(); // end of navigation source.
- Debug.Assert(path.Any() == false);
+ Debug.Assert(path.Count == 0);
}
///
@@ -312,7 +319,7 @@ private void RetrieveComplexPropertyPaths(IEdmEntityType entityType, ODataPath c
Utils.CheckArgumentNull(currentPath, nameof(currentPath));
Utils.CheckArgumentNull(convertSettings, nameof(convertSettings));
- if (!convertSettings.EnableNavigationPropertyPath) return;
+ if (!convertSettings.EnableNavigationPropertyPath || _model is null) return;
foreach (IEdmStructuralProperty sp in entityType.StructuralProperties()
.Where(x => x.Type.IsComplex() ||
@@ -327,9 +334,9 @@ private void RetrieveComplexPropertyPaths(IEdmEntityType entityType, ODataPath c
}
AppendPath(currentPath.Clone());
- if (sp.Type.IsCollection())
+ if (sp.Type.IsCollection() && sp.Type.Definition.AsElementType() is IEdmComplexType elemType)
{
- CreateTypeCastPaths(currentPath, convertSettings, sp.Type.Definition.AsElementType() as IEdmComplexType, sp, true);
+ CreateTypeCastPaths(currentPath, convertSettings, elemType, sp, true);
var isCountable = _model.GetRecord(targetPath, CapabilitiesConstants.CountRestrictions)?.IsCountable
?? _model.GetRecord(sp, CapabilitiesConstants.CountRestrictions)?.IsCountable
?? true;
@@ -345,7 +352,7 @@ private void RetrieveComplexPropertyPaths(IEdmEntityType entityType, ODataPath c
// Append navigation property paths for this complex property
RetrieveComplexTypeNavigationPropertyPaths(complexType, currentPath, convertSettings);
- // Traverse this complex property to rerieve nested navigation property paths
+ // Traverse this complex property to retrieve nested navigation property paths
TraverseComplexProperty(sp, currentPath, convertSettings);
}
@@ -373,7 +380,7 @@ private bool RetrieveComplexTypeNavigationPropertyPaths(IEdmComplexType complexT
.Distinct()
.Where(CanFilter);
- if (!navigationProperties.Any()) return false;
+ if (!navigationProperties.Any() || _model is null) return false;
foreach (var np in navigationProperties)
{
@@ -434,14 +441,14 @@ private bool ShouldCreateComplexPropertyPaths(IEdmStructuralProperty complexProp
if (!convertSettings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths)
return true;
- bool isReadable = _model.GetRecord(targetPath, CapabilitiesConstants.ReadRestrictions)?.Readable
- ?? _model.GetRecord(complexProperty, CapabilitiesConstants.ReadRestrictions)?.Readable
+ bool isReadable = _model?.GetRecord(targetPath, CapabilitiesConstants.ReadRestrictions)?.Readable
+ ?? _model?.GetRecord(complexProperty, CapabilitiesConstants.ReadRestrictions)?.Readable
?? false;
- bool isUpdatable = _model.GetRecord(targetPath, CapabilitiesConstants.UpdateRestrictions)?.Updatable
- ??_model.GetRecord(complexProperty, CapabilitiesConstants.UpdateRestrictions)?.Updatable
+ bool isUpdatable = _model?.GetRecord(targetPath, CapabilitiesConstants.UpdateRestrictions)?.Updatable
+ ??_model?.GetRecord(complexProperty, CapabilitiesConstants.UpdateRestrictions)?.Updatable
?? false;
- bool isInsertable = _model.GetRecord(targetPath, CapabilitiesConstants.InsertRestrictions)?.Insertable
- ?? _model.GetRecord(complexProperty, CapabilitiesConstants.InsertRestrictions)?.Insertable
+ bool isInsertable = _model?.GetRecord(targetPath, CapabilitiesConstants.InsertRestrictions)?.Insertable
+ ?? _model?.GetRecord(complexProperty, CapabilitiesConstants.InsertRestrictions)?.Insertable
?? false;
return isReadable || isUpdatable || isInsertable;
@@ -494,10 +501,10 @@ private void RetrieveMediaEntityStreamPaths(IEdmEntityType entityType, ODataPath
/// A stack that holds the visited navigation properties in the .
private void RetrieveNavigationPropertyPaths(
IEdmNavigationProperty navigationProperty,
- CountRestrictionsType count,
+ CountRestrictionsType? count,
ODataPath currentPath,
OpenApiConvertSettings convertSettings,
- Stack visitedNavigationProperties = null)
+ Stack? visitedNavigationProperties = null)
{
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
Utils.CheckArgumentNull(currentPath, nameof(currentPath));
@@ -518,18 +525,17 @@ private void RetrieveNavigationPropertyPaths(
}
// Get the annotatable navigation source for this navigation property.
- IEdmVocabularyAnnotatable annotatableNavigationSource = (currentPath.FirstSegment as ODataNavigationSourceSegment)?.NavigationSource as IEdmVocabularyAnnotatable;
- NavigationRestrictionsType navSourceRestrictionType = null;
- NavigationRestrictionsType navPropRestrictionType = null;
+ NavigationRestrictionsType? navSourceRestrictionType = null;
+ NavigationRestrictionsType? navPropRestrictionType = null;
// Get the NavigationRestrictions referenced by this navigation property: Can be defined in the navigation source or in-lined in the navigation property.
- if (annotatableNavigationSource != null)
+ if (currentPath.FirstSegment is ODataNavigationSourceSegment { NavigationSource: IEdmVocabularyAnnotatable annotatableNavigationSource } && _model is not null)
{
navSourceRestrictionType = _model.GetRecord(annotatableNavigationSource, CapabilitiesConstants.NavigationRestrictions);
navPropRestrictionType = _model.GetRecord(navigationProperty, CapabilitiesConstants.NavigationRestrictions);
}
- NavigationPropertyRestriction restriction = navSourceRestrictionType?.RestrictedProperties?
+ NavigationPropertyRestriction? restriction = navSourceRestrictionType?.RestrictedProperties?
.FirstOrDefault(r => r.NavigationProperty == currentPath.NavigationPropertyPath(navigationProperty.Name))
?? navPropRestrictionType?.RestrictedProperties?.FirstOrDefault();
@@ -549,22 +555,13 @@ private void RetrieveNavigationPropertyPaths(
visitedNavigationProperties.Push(navPropFullyQualifiedName);
// For fetching annotations
- var targetPath = currentPath.GetTargetPath(_model);
+ var targetPath = _model is null ? null : currentPath.GetTargetPath(_model);
// Check whether a collection-valued navigation property should be indexed by key value(s).
// Find indexability annotation annotated directly via NavigationPropertyRestriction.
- bool? annotatedIndexability = _model.GetBoolean(targetPath, CapabilitiesConstants.IndexableByKey)
- ?? _model.GetBoolean(navigationProperty, CapabilitiesConstants.IndexableByKey);
- bool indexableByKey = true;
-
- if (restriction?.IndexableByKey != null)
- {
- indexableByKey = (bool)restriction.IndexableByKey;
- }
- else if (annotatedIndexability != null)
- {
- indexableByKey = annotatedIndexability.Value;
- }
+ bool? annotatedIndexability = (string.IsNullOrEmpty(targetPath) ? null : _model?.GetBoolean(targetPath, CapabilitiesConstants.IndexableByKey))
+ ?? _model?.GetBoolean(navigationProperty, CapabilitiesConstants.IndexableByKey);
+ bool indexableByKey = restriction?.IndexableByKey ?? annotatedIndexability ?? true;
if (indexableByKey)
{
@@ -577,8 +574,8 @@ private void RetrieveNavigationPropertyPaths(
if (count == null)
{
// First, get the directly annotated restriction annotation of the navigation property
- count = _model.GetRecord(targetPath, CapabilitiesConstants.CountRestrictions)
- ?? _model.GetRecord(navigationProperty, CapabilitiesConstants.CountRestrictions);
+ count = (string.IsNullOrEmpty(targetPath) ? null : _model?.GetRecord(targetPath, CapabilitiesConstants.CountRestrictions))
+ ?? _model?.GetRecord(navigationProperty, CapabilitiesConstants.CountRestrictions);
createCountPath = count?.Countable;
}
@@ -735,13 +732,11 @@ private void CreateTypeCastPaths(ODataPath currentPath, OpenApiConvertSettings c
if(!convertSettings.EnableODataTypeCast)
return;
- var annotedTypeNames = GetDerivedTypeConstaintTypeNames(annotable);
+ var annotedTypeNames = GetDerivedTypeConstraintTypeNames(annotable);
if(!annotedTypeNames.Any() && convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments)
return; // we don't want to generate any downcast path item if there is no type cast annotation.
- var annotedTypeNamesSet = new HashSet(annotedTypeNames, StringComparer.OrdinalIgnoreCase);
-
bool filter(IEdmStructuredType x) =>
convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments && annotedTypeNames.Contains(x.FullTypeName()) ||
!convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments && (
@@ -750,16 +745,18 @@ bool filter(IEdmStructuredType x) =>
);
var targetTypes = _model
- .FindAllDerivedTypes(structuredType)
+ ?.FindAllDerivedTypes(structuredType)
.Where(x => (x.TypeKind == EdmTypeKind.Entity || x.TypeKind == EdmTypeKind.Complex) && filter(x))
.OfType()
.ToArray();
+ if (targetTypes is not { Length: > 0} || _model is null) return;
+
foreach (var targetType in targetTypes)
{
var targetTypeSegment = new ODataTypeCastSegment(targetType, _model);
- if (currentPath.Segments.Any(x => x.Identifier.Equals(targetTypeSegment.Identifier)))
+ if (currentPath.Segments.Any(x => x.Identifier?.Equals(targetTypeSegment.Identifier) ?? false))
{
// In case we have expanded a derived type's navigation property
// and we are in a cyclic loop where the expanded navigation property
@@ -802,7 +799,7 @@ bool filter(IEdmStructuredType x) =>
///
private void RetrieveBoundOperationPaths(OpenApiConvertSettings convertSettings)
{
- var edmOperations = _model.GetAllElements().OfType().Where(x => x.IsBound).ToArray();
+ var edmOperations = _model?.GetAllElements().OfType().Where(x => x.IsBound).ToArray() ?? [];
foreach (var edmOperation in edmOperations)
{
if (!CanFilter(edmOperation))
@@ -876,7 +873,7 @@ private void RetrieveBoundOperationPaths(OpenApiConvertSettings convertSettings)
&& operationSegment.Operation is IEdmFunction edmFunction
&& edmFunction.IsComposable
&& edmFunction.ReturnType != null
- && edmFunction.ReturnType.Definition is IEdmEntityType returnBindingEntityType);
+ && edmFunction.ReturnType.Definition is IEdmEntityType);
foreach( var functionPath in functionPaths)
{
@@ -902,11 +899,11 @@ functionPath.LastSegment is ODataOperationSegment &&
{
/* Get number of segments already appended after the first composable function segment
*/
- int composableFuncSegIndex = functionPath.Segments.IndexOf(
- functionPath.Segments.FirstOrDefault(
- x => x is ODataOperationSegment operationSegment &&
- operationSegment.Operation is IEdmFunction edmFunction &&
- edmFunction.IsComposable));
+ int composableFuncSegIndex = functionPath
+ .Segments
+ .OfType()
+ .FirstOrDefault(x => x.Operation is IEdmFunction {IsComposable: true}) is {} firstOperationSegment ?
+ functionPath.Segments.IndexOf(firstOperationSegment) : -1;
int currentDepth = functionPath.Count - composableFuncSegIndex - 1;
if (currentDepth < convertSettings.ComposableFunctionsExpansionDepth)
@@ -928,10 +925,10 @@ bool filter(IEdmNavigationSource z) =>
z.EntityType.FindAllBaseTypes().Contains(firstEntityType);
return new IEdmEntityType[] { firstEntityType }
- .Union(_model.EntityContainer.EntitySets()
- .Where(filter).Select(x => x.EntityType)) //Search all EntitySets
- .Union(_model.EntityContainer.Singletons()
- .Where(filter).Select(x => x.EntityType)) //Search all singletons
+ .Union(_model?.EntityContainer.EntitySets()
+ .Where(filter).Select(x => x.EntityType) ?? []) //Search all EntitySets
+ .Union(_model?.EntityContainer.Singletons()
+ .Where(filter).Select(x => x.EntityType) ?? []) //Search all singletons
.Distinct()
.ToList();
}
@@ -944,9 +941,9 @@ bool filter(IEdmNavigationSource z) =>
};
private void AppendBoundOperationOnNavigationSourcePath(IEdmOperation edmOperation, bool isCollection, IEdmEntityType bindingEntityType, OpenApiConvertSettings convertSettings)
{
- if (_allNavigationSourcePaths.TryGetValue(bindingEntityType, out IList value))
+ if (_allNavigationSourcePaths.TryGetValue(bindingEntityType, out var value))
{
- bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
+ bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
foreach (var subPath in value)
{
@@ -973,7 +970,7 @@ secondLastPathSegment is not ODataKeySegment &&
var annotatable = (lastPathSegment as ODataNavigationSourceSegment)?.NavigationSource as IEdmVocabularyAnnotatable;
annotatable ??= (lastPathSegment as ODataKeySegment)?.EntityType;
- if (annotatable != null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, annotatable))
+ if (annotatable != null && _model is not null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, annotatable))
{
// Check whether the navigation source is allowed to have an operation on the entity type
annotatable = (secondLastPathSegment as ODataNavigationSourceSegment)?.NavigationSource as IEdmVocabularyAnnotatable;
@@ -983,9 +980,12 @@ secondLastPathSegment is not ODataKeySegment &&
}
}
- ODataPath newPath = subPath.Clone();
- newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
- AppendPath(newPath);
+ if (_model is not null)
+ {
+ ODataPath newPath = subPath.Clone();
+ newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
+ AppendPath(newPath);
+ }
}
}
}
@@ -995,15 +995,15 @@ secondLastPathSegment is not ODataKeySegment &&
};
private void AppendBoundOperationOnNavigationPropertyPath(IEdmOperation edmOperation, bool isCollection, IEdmEntityType bindingEntityType)
{
- bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
+ bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
- if (_allNavigationPropertyPaths.TryGetValue(bindingEntityType, out IList value))
+ if (_allNavigationPropertyPaths.TryGetValue(bindingEntityType, out var value))
{
foreach (var path in value.Where(x => !_pathKindToSkipForNavigationProperties.Contains(x.Kind)))
{
- ODataNavigationPropertySegment npSegment = path.Segments.Last(s => s is ODataNavigationPropertySegment) as ODataNavigationPropertySegment;
+ ODataNavigationPropertySegment npSegment = path.Segments.OfType().Last();
- if (!EdmModelHelper.IsOperationAllowed(_model, edmOperation, npSegment.NavigationProperty, npSegment.NavigationProperty.ContainsTarget))
+ if (_model is not null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, npSegment.NavigationProperty, npSegment.NavigationProperty.ContainsTarget))
{
continue;
}
@@ -1030,9 +1030,12 @@ private void AppendBoundOperationOnNavigationPropertyPath(IEdmOperation edmOpera
}
}
- ODataPath newPath = path.Clone();
- newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
- AppendPath(newPath);
+ if (_model is not null)
+ {
+ ODataPath newPath = path.Clone();
+ newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
+ AppendPath(newPath);
+ }
}
}
}
@@ -1044,22 +1047,24 @@ private void AppendBoundOperationOnDerived(
OpenApiConvertSettings convertSettings)
{
if (!convertSettings.AppendBoundOperationsOnDerivedTypeCastSegments) return;
- bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
+ bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
+ if (_allNavigationSources is null) return;
foreach (var baseType in bindingEntityType.FindAllBaseTypes())
{
- if (_allNavigationSources.TryGetValue(baseType, out IList baseNavigationSource))
+ if (_allNavigationSources.TryGetValue(baseType, out var baseNavigationSource))
{
foreach (var ns in baseNavigationSource)
{
- if (HasUnsatisfiedDerivedTypeConstraint(
- ns as IEdmVocabularyAnnotatable,
+ if (ns is not IEdmVocabularyAnnotatable nsAnnotatable ||
+ HasUnsatisfiedDerivedTypeConstraint(
+ nsAnnotatable,
baseType,
convertSettings))
{
continue;
}
- if (!EdmModelHelper.IsOperationAllowed(_model, edmOperation, ns as IEdmVocabularyAnnotatable))
+ if (_model is null || !EdmModelHelper.IsOperationAllowed(_model, edmOperation, nsAnnotatable))
{
continue;
}
@@ -1100,11 +1105,11 @@ private bool HasUnsatisfiedDerivedTypeConstraint(
OpenApiConvertSettings convertSettings)
{
return convertSettings.RequireDerivedTypesConstraintForBoundOperations &&
- !GetDerivedTypeConstaintTypeNames(annotatable)
+ !GetDerivedTypeConstraintTypeNames(annotatable)
.Any(c => c.Equals(baseType.FullName(), StringComparison.OrdinalIgnoreCase));
}
- private IEnumerable GetDerivedTypeConstaintTypeNames(IEdmVocabularyAnnotatable annotatable) =>
- _model.GetCollection(annotatable, "Org.OData.Validation.V1.DerivedTypeConstraint") ?? Enumerable.Empty();
+ private IEnumerable GetDerivedTypeConstraintTypeNames(IEdmVocabularyAnnotatable annotatable) =>
+ _model?.GetCollection(annotatable, "Org.OData.Validation.V1.DerivedTypeConstraint") ?? [];
private void AppendBoundOperationOnDerivedNavigationPropertyPath(
IEdmOperation edmOperation,
@@ -1113,11 +1118,11 @@ private void AppendBoundOperationOnDerivedNavigationPropertyPath(
OpenApiConvertSettings convertSettings)
{
if (!convertSettings.AppendBoundOperationsOnDerivedTypeCastSegments) return;
- bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
+ bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
foreach (var baseType in bindingEntityType.FindAllBaseTypes())
{
- if (_allNavigationPropertyPaths.TryGetValue(baseType, out IList paths))
+ if (_allNavigationPropertyPaths.TryGetValue(baseType, out var paths))
{
foreach (var path in paths.Where(x => !_pathKindToSkipForNavigationProperties.Contains(x.Kind)))
{
@@ -1127,7 +1132,7 @@ private void AppendBoundOperationOnDerivedNavigationPropertyPath(
continue;
}
- if (!EdmModelHelper.IsOperationAllowed(_model, edmOperation, npSegment.NavigationProperty, npSegment.NavigationProperty.ContainsTarget))
+ if (_model is not null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, npSegment.NavigationProperty, npSegment.NavigationProperty.ContainsTarget))
{
continue;
}
@@ -1163,10 +1168,13 @@ private void AppendBoundOperationOnDerivedNavigationPropertyPath(
continue;
}
- ODataPath newPath = path.Clone();
- newPath.Push(new ODataTypeCastSegment(bindingEntityType, _model));
- newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
- AppendPath(newPath);
+ if (_model is not null)
+ {
+ ODataPath newPath = path.Clone();
+ newPath.Push(new ODataTypeCastSegment(bindingEntityType, _model));
+ newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
+ AppendPath(newPath);
+ }
}
}
}
@@ -1174,7 +1182,7 @@ private void AppendBoundOperationOnDerivedNavigationPropertyPath(
private void AppendBoundOperationOnOperationPath(IEdmOperation edmOperation, bool isCollection, IEdmEntityType bindingEntityType)
{
- bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
+ bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
// only composable functions
var paths = _allOperationPaths.Where(x => x.LastSegment is ODataOperationSegment operationSegment
@@ -1188,7 +1196,7 @@ private void AppendBoundOperationOnOperationPath(IEdmOperation edmOperation, boo
|| operationSegment.Operation is not IEdmFunction edmFunction || !edmFunction.IsComposable
|| edmFunction.ReturnType == null || !edmFunction.ReturnType.Definition.Equals(bindingEntityType)
|| isCollection
- || !EdmModelHelper.IsOperationAllowed(_model, edmOperation, operationSegment.Operation, true))
+ || _model is not null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, operationSegment.Operation, true))
{
continue;
}
@@ -1200,7 +1208,10 @@ private void AppendBoundOperationOnOperationPath(IEdmOperation edmOperation, boo
}
ODataPath newOperationPath = path.Clone();
- newOperationPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
+ if (_model is not null)
+ {
+ newOperationPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
+ }
AppendPath(newOperationPath);
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataRefSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataRefSegment.cs
index a1047d724..471e5ed63 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataRefSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataRefSegment.cs
@@ -28,7 +28,7 @@ private ODataRefSegment()
}
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.Ref;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs
index 7a262d10b..b9eeb31a4 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs
@@ -86,7 +86,7 @@ public abstract class ODataSegment
///
/// Gets the entity type of current segment.
///
- public virtual IEdmEntityType EntityType => throw new NotImplementedException();
+ public virtual IEdmEntityType? EntityType => throw new NotImplementedException();
///
/// Gets the kind of this segment.
@@ -96,16 +96,16 @@ public abstract class ODataSegment
///
/// Gets the identifier of this segment.
///
- public abstract string Identifier { get; }
+ public abstract string? Identifier { get; }
///
/// Gets the path item name for this segment.
///
/// The settings.
/// The path item name.
- public string GetPathItemName(OpenApiConvertSettings settings)
+ public string? GetPathItemName(OpenApiConvertSettings settings)
{
- return GetPathItemName(settings, new HashSet());
+ return GetPathItemName(settings, []);
}
///
/// Provides a suffix for the operation id based on the operation path.
@@ -113,7 +113,7 @@ public string GetPathItemName(OpenApiConvertSettings settings)
/// Path to use to deduplicate.
/// The settings.
///The suffix.
- public string GetPathHash(OpenApiConvertSettings settings, ODataPath path = default)
+ public string GetPathHash(OpenApiConvertSettings settings, ODataPath? path = default)
{
var suffix = string.Join("/", path?.Segments.Select(x => x.Identifier).Distinct() ?? Enumerable.Empty());
return (GetPathItemName(settings) + suffix).GetHashSHA256().Substring(0, 4);
@@ -125,7 +125,7 @@ public string GetPathHash(OpenApiConvertSettings settings, ODataPath path = defa
/// The settings.
/// The existing parameters.
/// The path item name.
- public abstract string GetPathItemName(OpenApiConvertSettings settings, HashSet parameters);
+ public abstract string? GetPathItemName(OpenApiConvertSettings settings, HashSet parameters);
///
/// Returns the list of this segment refers to.
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs
index 02101a887..01cd11425 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs
@@ -16,7 +16,7 @@ namespace Microsoft.OpenApi.OData.Edm
public class ODataStreamContentSegment : ODataSegment
{
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.StreamContent;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs
index 06d52c365..0ee79bb6b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs
@@ -26,7 +26,7 @@ public ODataStreamPropertySegment(string streamPropertyName)
}
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.StreamProperty;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs
index 47da7fd4f..e7a3ff3c0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs
@@ -27,7 +27,7 @@ public ODataTypeCastSegment(IEdmStructuredType structuredType, IEdmModel model)
private readonly IEdmModel _model;
///
- public override IEdmEntityType EntityType => null;
+ public override IEdmEntityType? EntityType => null;
///
public override ODataSegmentKind Kind => ODataSegmentKind.TypeCast;
@@ -43,7 +43,7 @@ public ODataTypeCastSegment(IEdmStructuredType structuredType, IEdmModel model)
///
public override IEnumerable GetAnnotables()
{
- return [StructuredType as IEdmVocabularyAnnotatable];
+ return StructuredType is IEdmVocabularyAnnotatable annotable ? [annotable] : [];
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs
index 5d8dc6d4a..3010a06c9 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs
@@ -41,7 +41,7 @@ internal static class RecordExpressionExtensions
/// The given record.
/// The property name.
/// The property string value.
- public static string GetString(this IEdmRecordExpression record, string propertyName)
+ public static string? GetString(this IEdmRecordExpression record, string propertyName)
{
Utils.CheckArgumentNull(record, nameof(record));
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
@@ -127,7 +127,7 @@ property.Value is IEdmEnumMemberExpression value &&
/// The record expression.
/// The property name.
/// The collection or null.
- public static T GetRecord(this IEdmRecordExpression record, string propertyName)
+ public static T? GetRecord(this IEdmRecordExpression record, string propertyName)
where T : IRecord, new()
{
Utils.CheckArgumentNull(record, nameof(record));
@@ -150,7 +150,7 @@ public static T GetRecord(this IEdmRecordExpression record, string propertyNa
/// The record expression.
/// The property name.
/// The property path or null.
- public static string GetPropertyPath(this IEdmRecordExpression record, string propertyName)
+ public static string? GetPropertyPath(this IEdmRecordExpression record, string propertyName)
{
Utils.CheckArgumentNull(record, nameof(record));
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
@@ -167,7 +167,7 @@ public static string GetPropertyPath(this IEdmRecordExpression record, string pr
/// The record expression.
/// The property name.
/// The collection of property path or null.
- public static IList GetCollectionPropertyPath(this IEdmRecordExpression record, string propertyName)
+ public static IList? GetCollectionPropertyPath(this IEdmRecordExpression record, string propertyName)
{
Utils.CheckArgumentNull(record, nameof(record));
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
@@ -196,7 +196,7 @@ public static IList GetCollectionPropertyPath(this IEdmRecordExpression
/// The record expression.
/// The property name.
/// The collection of string or null.
- public static IList GetCollection(this IEdmRecordExpression record, string propertyName)
+ public static IList? GetCollection(this IEdmRecordExpression record, string propertyName)
{
Utils.CheckArgumentNull(record, nameof(record));
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
@@ -221,7 +221,7 @@ public static IList GetCollection(this IEdmRecordExpression record, stri
/// The record expression.
/// The property name.
/// The collection or null.
- public static IList GetCollection(this IEdmRecordExpression record, string propertyName)
+ public static IList? GetCollection(this IEdmRecordExpression record, string propertyName)
where T : IRecord, new()
{
Utils.CheckArgumentNull(record, nameof(record));
diff --git a/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs
index 5fe3f4b07..a1af2a25e 100644
--- a/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs
@@ -3,9 +3,11 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System.Collections.Generic;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Validation;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
@@ -39,22 +41,20 @@ public static OpenApiDocument ConvertToOpenApi(this IEdmModel model, OpenApiConv
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(settings, nameof(settings));
- if (settings.VerifyEdmModel)
- {
- if (!model.Validate(out var errors))
+ if (settings.VerifyEdmModel && !model.Validate(out var errors))
+ {
+ OpenApiDocument document = new();
+ int index = 1;
+ document.Extensions ??= new Dictionary();
+ foreach (var error in errors)
{
- OpenApiDocument document = new();
- int index = 1;
- foreach (var error in errors)
- {
- document.Extensions.Add(Constants.xMsEdmModelError + index++, new OpenApiAny(error.ToString()));
- }
-
- return document;
+ document.Extensions.Add(Constants.xMsEdmModelError + index++, new OpenApiAny(error.ToString()));
}
+
+ return document;
}
- ODataContext context = new(model, settings);
+ ODataContext context = new(model, settings);
return context.CreateDocument();
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Extensions/IODataRoutePathPrefixProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Extensions/IODataRoutePathPrefixProvider.cs
index 22b33398f..edff4e306 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Extensions/IODataRoutePathPrefixProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Extensions/IODataRoutePathPrefixProvider.cs
@@ -16,11 +16,11 @@ public interface IODataRoutePathPrefixProvider
///
/// The route prefix.
///
- public string PathPrefix { get; }
+ public string? PathPrefix { get; }
///
/// The route prefix parameters.
///
- public IEnumerable Parameters { get; }
+ public IEnumerable? Parameters { get; }
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Extensions/ODataRoutePathPrefixProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Extensions/ODataRoutePathPrefixProvider.cs
index 61b409269..5a9d864c3 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Extensions/ODataRoutePathPrefixProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Extensions/ODataRoutePathPrefixProvider.cs
@@ -16,11 +16,11 @@ public class ODataRoutePathPrefixProvider : IODataRoutePathPrefixProvider
///
/// Gets/sets the path prefix.
///
- public string PathPrefix { get; set; }
+ public string? PathPrefix { get; set; }
///
/// Gets/sets the associated parameters for the path prefix.
///
- public IEnumerable Parameters { get; set; }
+ public IEnumerable? Parameters { get; set; }
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs
index 64fe4417a..5d5ff3997 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs
@@ -32,9 +32,12 @@ public static void AddComponentsToDocument(this ODataContext context, OpenApiDoc
context.AddRequestBodiesToDocument(document);
context.AddExamplesToDocument(document);
context.AddSecuritySchemesToDocument(document);
- document.Components.Links = null;
- document.Components.Callbacks = null;
- document.Components.Extensions = null;
+ if (document.Components is not null)
+ {
+ document.Components.Links = null;
+ document.Components.Callbacks = null;
+ document.Components.Extensions = null;
+ }
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs
index fc315fdcb..1315f99e3 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs
@@ -47,7 +47,7 @@ public static void AddExamplesToDocument(this ODataContext context, OpenApiDocum
}
}
- private static OpenApiExample CreateExample(this ODataContext context, IEdmType edmType, OpenApiDocument document)
+ private static OpenApiExample? CreateExample(this ODataContext context, IEdmType edmType, OpenApiDocument document)
{
Debug.Assert(context != null);
Debug.Assert(edmType != null);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs
index 085cb5bb8..195893ef8 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs
@@ -61,7 +61,7 @@ private static string GetTitle(this ODataContext context)
}
// If no Core.Description is present, a default title has to be provided as this is a required OpenAPI field.
- string namespaceName = context.Model.EntityContainer != null ?
+ var namespaceName = context.Model.EntityContainer != null ?
context.Model.EntityContainer.Namespace :
context.Model.DeclaredNamespaces.FirstOrDefault();
@@ -100,7 +100,7 @@ private static string GetDescription(this ODataContext context)
return "This OData service is located at " + context.Settings.ServiceRoot.OriginalString;
}
- private static Dictionary GetExtensions(this ODataContext context)
+ private static Dictionary? GetExtensions(this ODataContext context)
{
Debug.Assert(context != null);
@@ -113,7 +113,7 @@ private static Dictionary GetExtensions(this ODataCon
new OpenApiAny(new JsonObject
{
{ "toolName", "Microsoft.OpenApi.OData" },
- { "toolVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString() }
+ { "toolVersion", Assembly.GetExecutingAssembly().GetName().Version?.ToString() }
})
}
};
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs
index 5fb7804ea..b852e2e43 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs
@@ -10,6 +10,7 @@
using Microsoft.OpenApi.OData.Edm;
using System.Linq;
using Microsoft.OpenApi.Models.Interfaces;
+using System;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -31,7 +32,7 @@ internal static class OpenApiLinkGenerator
/// The created dictionary of object.
public static IDictionary CreateLinks(this ODataContext context,
IEdmEntityType entityType, string entityName, string entityKind, ODataPath path,
- IList parameters = null, string navPropOperationId = null)
+ IList? parameters = null, string? navPropOperationId = null)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(entityType, nameof(entityType));
@@ -47,7 +48,8 @@ public static IDictionary CreateLinks(this ODataContext co
foreach (var parameter in parameters)
{
if (!string.IsNullOrEmpty(parameter.Description) &&
- parameter.Description.ToLower().Contains("key"))
+ parameter.Description.Contains("key", StringComparison.OrdinalIgnoreCase) &&
+ !string.IsNullOrEmpty(parameter.Name))
{
pathKeyNames.Add(parameter.Name);
}
@@ -68,7 +70,7 @@ public static IDictionary CreateLinks(this ODataContext co
switch (entityKind)
{
- case "Navigation": // just for contained navigations
+ case "Navigation" when !string.IsNullOrEmpty(navPropOperationId): // just for contained navigations
operationPrefix = navPropOperationId;
break;
default: // EntitySet, Entity, Singleton
@@ -115,11 +117,12 @@ public static IDictionary CreateLinks(this ODataContext co
{
foreach (var operationPath in operationPaths)
{
+ if (operationPath.LastSegment?.Identifier is null) continue;
OpenApiLink link = new()
{
OperationId = string.Join(".", operationPath.Segments.Select(x =>
{
- return x.Kind.Equals(ODataSegmentKind.Key) ? x.EntityType.Name : x.Identifier;
+ return x.Kind.Equals(ODataSegmentKind.Key) && x.EntityType is not null ? x.EntityType.Name : x.Identifier;
}))
};
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs
index dad145a3d..8c986e22b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs
@@ -17,6 +17,7 @@
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Interfaces;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -71,7 +72,7 @@ public static IList CreateParameters(this ODataContext contex
/// The created list of .
public static IList CreateParameters(this ODataContext context, IEdmFunction function,
OpenApiDocument document,
- IDictionary parameterNameMapping = null)
+ IDictionary? parameterNameMapping = null)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(function, nameof(function));
@@ -160,7 +161,7 @@ public static IList CreateParameters(this ODataContext contex
/// The created list of .
public static IList CreateKeyParameters(this ODataContext context, ODataKeySegment keySegment,
OpenApiDocument document,
- IDictionary parameterNameMapping = null)
+ IDictionary? parameterNameMapping = null)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(keySegment, nameof(keySegment));
@@ -193,6 +194,7 @@ public static IList CreateKeyParameters(this ODataContext cont
Schema = context.CreateEdmTypeSchemaForParameter(keys[0].Type, document)
};
+ parameter.Extensions ??= new Dictionary();
parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiAny(entityType.Name));
parameters.Add(parameter);
}
@@ -218,6 +220,7 @@ public static IList CreateKeyParameters(this ODataContext cont
parameter.Description += $", {keyProperty.Name}={quote}{{{parameter.Name}}}{quote}";
}
+ parameter.Extensions ??= new Dictionary();
parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiAny(entityType.Name));
parameters.Add(parameter);
}
@@ -341,21 +344,21 @@ public static List CreatePathParameters(this ODataPath path,
/// The new OpenApiParameter to be appended
public static void AppendParameter(this IList parameters, IOpenApiParameter parameter)
{
- HashSet parametersSet = new(parameters.Select(p => p.Name));
+ HashSet parametersSet = new(parameters.Select(p => p.Name).OfType());
- string parameterName = parameter.Name;
- int index = 1;
- while (parametersSet.Contains(parameterName))
- {
- parameterName += index.ToString();
- index++;
- }
-
- if (parameter is OpenApiParameter openApiParameter)
+ if (parameter.Name is not string parameterName &&
+ parameter is OpenApiParameter openApiParameter)
{
+ parameterName = string.Empty;
+ int index = 1;
+ while (parametersSet.Contains(parameterName))
+ {
+ parameterName += index.ToString();
+ index++;
+ }
openApiParameter.Name = parameterName;
}
- parametersSet.Add(parameterName);
+
parameters.Add(parameter);
}
@@ -366,7 +369,7 @@ public static void AppendParameter(this IList parameters, IOp
/// The Edm annotation target.
/// The Open API document.
/// The created or null.
- public static IOpenApiParameter CreateTop(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
+ public static IOpenApiParameter? CreateTop(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
@@ -388,7 +391,7 @@ public static IOpenApiParameter CreateTop(this ODataContext context, IEdmVocabul
/// The string representation of the Edm target path.
/// The Open API document to use to build references.
///
- public static IOpenApiParameter CreateTop(this ODataContext context, string targetPath, OpenApiDocument document)
+ public static IOpenApiParameter? CreateTop(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -408,7 +411,7 @@ public static IOpenApiParameter CreateTop(this ODataContext context, string targ
/// The Edm annotation target.
/// The Open API document to use to build references.
/// The created or null.
- public static IOpenApiParameter CreateSkip(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
+ public static IOpenApiParameter? CreateSkip(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
@@ -430,7 +433,7 @@ public static IOpenApiParameter CreateSkip(this ODataContext context, IEdmVocabu
/// The string representation of the Edm target path.
/// The Open API document to use to build references.
///
- public static IOpenApiParameter CreateSkip(this ODataContext context, string targetPath, OpenApiDocument document)
+ public static IOpenApiParameter? CreateSkip(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -450,14 +453,13 @@ public static IOpenApiParameter CreateSkip(this ODataContext context, string tar
/// The Edm annotation target.
/// The Open API document to use to build references.
/// The created or null.
- public static IOpenApiParameter CreateSearch(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
+ public static IOpenApiParameter? CreateSearch(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
Utils.CheckArgumentNull(document, nameof(document));
- SearchRestrictionsType search = context.Model.GetRecord(target, CapabilitiesConstants.SearchRestrictions);
- if (search == null || search.IsSearchable)
+ if (context.Model.GetRecord(target, CapabilitiesConstants.SearchRestrictions) is not {} search || search.IsSearchable)
{
return new OpenApiParameterReference("search", document);
}
@@ -471,7 +473,7 @@ public static IOpenApiParameter CreateSearch(this ODataContext context, IEdmVoca
/// The string representation of the Edm target path.
/// The Open API document to use to build references.
///
- public static IOpenApiParameter CreateSearch(this ODataContext context, string targetPath, OpenApiDocument document)
+ public static IOpenApiParameter? CreateSearch(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -491,14 +493,13 @@ public static IOpenApiParameter CreateSearch(this ODataContext context, string t
/// The Edm annotation target.
/// The Open API document to use to build references.
/// The created or null.
- public static IOpenApiParameter CreateCount(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
+ public static IOpenApiParameter? CreateCount(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
Utils.CheckArgumentNull(document, nameof(document));
- CountRestrictionsType count = context.Model.GetRecord(target, CapabilitiesConstants.CountRestrictions);
- if (count == null || count.IsCountable)
+ if (context.Model.GetRecord(target, CapabilitiesConstants.CountRestrictions) is not {} count || count.IsCountable)
{
return new OpenApiParameterReference("count", document);
}
@@ -513,7 +514,7 @@ public static IOpenApiParameter CreateCount(this ODataContext context, IEdmVocab
/// The string representation of the Edm target path.
/// The Open API document to use to build references.
///
- public static IOpenApiParameter CreateCount(this ODataContext context, string targetPath, OpenApiDocument document)
+ public static IOpenApiParameter? CreateCount(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -533,14 +534,13 @@ public static IOpenApiParameter CreateCount(this ODataContext context, string ta
/// The Edm annotation target.
/// The Open API document to use to build references.
/// The created or null.
- public static IOpenApiParameter CreateFilter(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
+ public static IOpenApiParameter? CreateFilter(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
Utils.CheckArgumentNull(document, nameof(document));
- FilterRestrictionsType filter = context.Model.GetRecord(target, CapabilitiesConstants.FilterRestrictions);
- if (filter == null || filter.IsFilterable)
+ if (context.Model.GetRecord(target, CapabilitiesConstants.FilterRestrictions) is not {} filter || filter.IsFilterable)
{
return new OpenApiParameterReference("filter", document);
}
@@ -555,7 +555,7 @@ public static IOpenApiParameter CreateFilter(this ODataContext context, IEdmVoca
/// The string representation of the Edm target path.
/// The Open API document to use to build references.
///
- public static IOpenApiParameter CreateFilter(this ODataContext context, string targetPath, OpenApiDocument document)
+ public static IOpenApiParameter? CreateFilter(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -567,7 +567,7 @@ public static IOpenApiParameter CreateFilter(this ODataContext context, string t
return context.CreateFilter(target, document);
}
- public static OpenApiParameter CreateOrderBy(this ODataContext context, string targetPath, IEdmEntityType entityType)
+ public static OpenApiParameter? CreateOrderBy(this ODataContext context, string targetPath, IEdmEntityType entityType)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -579,7 +579,7 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, string t
return context.CreateOrderBy(target, entityType);
}
- public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmEntitySet entitySet)
+ public static OpenApiParameter? CreateOrderBy(this ODataContext context, IEdmEntitySet entitySet)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(entitySet, nameof(entitySet));
@@ -587,7 +587,7 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmEnti
return context.CreateOrderBy(entitySet, entitySet.EntityType);
}
- public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmSingleton singleton)
+ public static OpenApiParameter? CreateOrderBy(this ODataContext context, IEdmSingleton singleton)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(singleton, nameof(singleton));
@@ -595,7 +595,7 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmSing
return context.CreateOrderBy(singleton, singleton.EntityType);
}
- public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmNavigationProperty navigationProperty)
+ public static OpenApiParameter? CreateOrderBy(this ODataContext context, IEdmNavigationProperty navigationProperty)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
@@ -610,12 +610,12 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmNavi
/// The Edm annotation target.
/// The Edm Entity type.
/// The created or null.
- public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmEntityType entityType)
+ public static OpenApiParameter? CreateOrderBy(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmEntityType entityType)
{// patchwork to avoid breaking changes
return context.CreateOrderBy(target, entityType as IEdmStructuredType);
}
- public static OpenApiParameter CreateOrderBy(this ODataContext context, string targetPath, IEdmStructuredType structuredType)
+ public static OpenApiParameter? CreateOrderBy(this ODataContext context, string targetPath, IEdmStructuredType structuredType)
{
IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
if (target == null)
@@ -624,13 +624,13 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, string t
return context.CreateOrderBy(target, structuredType);
}
- public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmStructuredType structuredType)
+ public static OpenApiParameter? CreateOrderBy(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmStructuredType structuredType)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
- SortRestrictionsType sort = context.Model.GetRecord(target, CapabilitiesConstants.SortRestrictions);
+ var sort = context.Model.GetRecord(target, CapabilitiesConstants.SortRestrictions);
if (sort != null && !sort.IsSortable)
{
return null;
@@ -684,19 +684,18 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmVoca
};
}
- public static OpenApiParameter CreateSelect(this ODataContext context, string targetPath, IEdmEntityType entityType)
+ public static OpenApiParameter? CreateSelect(this ODataContext context, string targetPath, IEdmEntityType entityType)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
- IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
- if (target == null)
+ if (context.Model.GetTargetPath(targetPath) is not {} target)
return null;
return context.CreateSelect(target, entityType);
}
- public static OpenApiParameter CreateSelect(this ODataContext context, IEdmEntitySet entitySet)
+ public static OpenApiParameter? CreateSelect(this ODataContext context, IEdmEntitySet entitySet)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(entitySet, nameof(entitySet));
@@ -704,7 +703,7 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmEntit
return context.CreateSelect(entitySet, entitySet.EntityType);
}
- public static OpenApiParameter CreateSelect(this ODataContext context, IEdmSingleton singleton)
+ public static OpenApiParameter? CreateSelect(this ODataContext context, IEdmSingleton singleton)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(singleton, nameof(singleton));
@@ -712,7 +711,7 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmSingl
return context.CreateSelect(singleton, singleton.EntityType);
}
- public static OpenApiParameter CreateSelect(this ODataContext context, IEdmNavigationProperty navigationProperty)
+ public static OpenApiParameter? CreateSelect(this ODataContext context, IEdmNavigationProperty navigationProperty)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
@@ -727,12 +726,12 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmNavig
/// The Edm target.
/// The Edm entity type.
/// The created or null.
- public static OpenApiParameter CreateSelect(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmEntityType entityType)
+ public static OpenApiParameter? CreateSelect(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmEntityType entityType)
{ // patchwork to avoid breaking changes
return context.CreateSelect(target, entityType as IEdmStructuredType);
}
- public static OpenApiParameter CreateSelect(this ODataContext context, string targetPath, IEdmStructuredType structuredType)
+ public static OpenApiParameter? CreateSelect(this ODataContext context, string targetPath, IEdmStructuredType structuredType)
{
IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
if (target == null)
@@ -741,13 +740,13 @@ public static OpenApiParameter CreateSelect(this ODataContext context, string ta
return context.CreateSelect(target, structuredType);
}
- public static OpenApiParameter CreateSelect(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmStructuredType structuredType)
+ public static OpenApiParameter? CreateSelect(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmStructuredType structuredType)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
- NavigationRestrictionsType navigation = context.Model.GetRecord(target, CapabilitiesConstants.NavigationRestrictions);
+ var navigation = context.Model.GetRecord(target, CapabilitiesConstants.NavigationRestrictions);
if (navigation != null && !navigation.IsNavigable)
{
return null;
@@ -790,7 +789,7 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmVocab
};
}
- public static OpenApiParameter CreateExpand(this ODataContext context, string targetPath, IEdmEntityType entityType)
+ public static OpenApiParameter? CreateExpand(this ODataContext context, string targetPath, IEdmEntityType entityType)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -802,7 +801,7 @@ public static OpenApiParameter CreateExpand(this ODataContext context, string ta
return context.CreateExpand(target, entityType);
}
- public static OpenApiParameter CreateExpand(this ODataContext context, IEdmEntitySet entitySet)
+ public static OpenApiParameter? CreateExpand(this ODataContext context, IEdmEntitySet entitySet)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(entitySet, nameof(entitySet));
@@ -810,7 +809,7 @@ public static OpenApiParameter CreateExpand(this ODataContext context, IEdmEntit
return context.CreateExpand(entitySet, entitySet.EntityType);
}
- public static OpenApiParameter CreateExpand(this ODataContext context, IEdmSingleton singleton)
+ public static OpenApiParameter? CreateExpand(this ODataContext context, IEdmSingleton singleton)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(singleton, nameof(singleton));
@@ -818,7 +817,7 @@ public static OpenApiParameter CreateExpand(this ODataContext context, IEdmSingl
return context.CreateExpand(singleton, singleton.EntityType);
}
- public static OpenApiParameter CreateExpand(this ODataContext context, IEdmNavigationProperty navigationProperty)
+ public static OpenApiParameter? CreateExpand(this ODataContext context, IEdmNavigationProperty navigationProperty)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
@@ -833,12 +832,12 @@ public static OpenApiParameter CreateExpand(this ODataContext context, IEdmNavig
/// The edm entity path.
/// The edm entity path.
/// The created or null.
- public static OpenApiParameter CreateExpand(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmEntityType entityType)
+ public static OpenApiParameter? CreateExpand(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmEntityType entityType)
{ // patchwork to avoid breaking changes
return context.CreateExpand(target, entityType as IEdmStructuredType);
}
- public static OpenApiParameter CreateExpand(this ODataContext context, string targetPath, IEdmStructuredType structuredType)
+ public static OpenApiParameter? CreateExpand(this ODataContext context, string targetPath, IEdmStructuredType structuredType)
{
IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
if (target == null)
@@ -847,13 +846,13 @@ public static OpenApiParameter CreateExpand(this ODataContext context, string ta
return context.CreateExpand(target, structuredType);
}
- public static OpenApiParameter CreateExpand(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmStructuredType structuredType)
+ public static OpenApiParameter? CreateExpand(this ODataContext context, IEdmVocabularyAnnotatable target, IEdmStructuredType structuredType)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
- ExpandRestrictionsType expand = context.Model.GetRecord(target, CapabilitiesConstants.ExpandRestrictions);
+ var expand = context.Model.GetRecord(target, CapabilitiesConstants.ExpandRestrictions);
if (expand != null && !expand.IsExpandable)
{
return null;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs
index 5aa19ad11..69f824475 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs
@@ -4,7 +4,6 @@
// ------------------------------------------------------------
using System.Collections.Generic;
-using System.Linq;
using System.Net.Http;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
@@ -40,14 +39,13 @@ public static void AddPathItemsToDocument(this ODataContext context, OpenApiDocu
settings.EnableKeyAsSegment = context.KeyAsSegment;
foreach (ODataPath path in context.AllPaths)
{
- IPathItemHandler handler = context.PathItemHandlerProvider.GetHandler(path.Kind, document);
+ var handler = context.PathItemHandlerProvider.GetHandler(path.Kind, document);
if (handler == null)
{
continue;
}
- OpenApiPathItem pathItem = handler.CreatePathItem(context, path);
- if (!pathItem.Operations.Any())
+ if (handler.CreatePathItem(context, path) is not {Operations.Count: > 0} pathItem)
{
continue;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs
index ffb8f0c10..2e23c398a 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs
@@ -26,7 +26,7 @@ internal static class OpenApiRequestBodyGenerator
/// The Edm action import.
/// The OpenApi document to lookup references.
/// The created or null.
- public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmActionImport actionImport, OpenApiDocument document)
+ public static OpenApiRequestBody? CreateRequestBody(this ODataContext context, IEdmActionImport actionImport, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(actionImport, nameof(actionImport));
@@ -42,7 +42,7 @@ public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IE
/// The Edm action.
/// The OpenApi document to lookup references.
/// The created or null.
- public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmAction action, OpenApiDocument document)
+ public static OpenApiRequestBody? CreateRequestBody(this ODataContext context, IEdmAction action, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(action, nameof(action));
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
index c0cfa4f01..25ec6f75c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
@@ -28,7 +27,7 @@ internal static class OpenApiResponseGenerator
/// The status code.
/// The OpenApi document to lookup references.
/// The created .
- public static IOpenApiResponse GetResponse(this string statusCode, OpenApiDocument document)
+ public static IOpenApiResponse? GetResponse(this string statusCode, OpenApiDocument document)
{
return statusCode switch {
Constants.StatusCodeDefault => new OpenApiResponseReference(Constants.Error, document),
@@ -82,8 +81,7 @@ public static void AddResponsesToDocument(this ODataContext context, OpenApiDocu
foreach (IEdmOperation operation in context.Model.SchemaElements.OfType()
.Where(op => context.Model.OperationTargetsMultiplePaths(op)))
{
- OpenApiResponse response = context.CreateOperationResponse(operation, document);
- if (response != null)
+ if (context.CreateOperationResponse(operation, document) is {} response)
responses[$"{operation.Name}Response"] = response;
}
@@ -123,9 +121,9 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp
OpenApiResponses responses = new();
- if (operation.IsAction() && operation.ReturnType == null)
+ if (operation.IsAction() && operation.ReturnType == null && Constants.StatusCode204.GetResponse(document) is {} x204Response)
{
- responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse(document));
+ responses.Add(Constants.StatusCode204, x204Response);
}
else if (context.Model.OperationTargetsMultiplePaths(operation))
{
@@ -134,26 +132,27 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp
new OpenApiResponseReference($"{operation.Name}Response", document)
);
}
- else
+ else if (context.CreateOperationResponse(operation, document) is {} successResponse)
{
- OpenApiResponse response = context.CreateOperationResponse(operation, document);
- responses.Add(context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, response);
+ responses.Add(context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, successResponse);
}
- if (context.Settings.ErrorResponsesAsDefault)
+ if (context.Settings.ErrorResponsesAsDefault && Constants.StatusCodeDefault.GetResponse(document) is {} defaultResponse)
{
- responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse(document));
+ responses.Add(Constants.StatusCodeDefault, defaultResponse);
}
else
{
- responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse(document));
- responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse(document));
+ if (Constants.StatusCodeClass4XX.GetResponse(document) is {} x4Response)
+ responses.Add(Constants.StatusCodeClass4XX, x4Response);
+ if (Constants.StatusCodeClass5XX.GetResponse(document) is {} x5Response)
+ responses.Add(Constants.StatusCodeClass5XX, x5Response);
}
return responses;
}
- public static OpenApiResponse CreateOperationResponse(this ODataContext context, IEdmOperation operation, OpenApiDocument document)
+ public static OpenApiResponse? CreateOperationResponse(this ODataContext context, IEdmOperation operation, OpenApiDocument document)
{
if (operation.ReturnType == null)
return null;
@@ -232,7 +231,7 @@ public static OpenApiResponse CreateOperationResponse(this ODataContext context,
schema = context.CreateEdmTypeSchema(operation.ReturnType, document);
}
- string mediaType = Constants.ApplicationJsonMediaType;
+ string? mediaType = Constants.ApplicationJsonMediaType;
if (operation.ReturnType.AsPrimitive()?.PrimitiveKind() == EdmPrimitiveTypeKind.Stream)
{
mediaType = context.Model.GetString(operation, CoreConstants.MediaType);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs
index 91648b010..1cb0941da 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs
@@ -106,6 +106,7 @@ public static void AddSchemasToDocument(this ODataContext context, OpenApiDocume
};
document.AddComponent(Constants.BaseCollectionPaginationCountResponse, responseSchema);
+ responseSchema.Properties ??= new Dictionary();
if (context.Settings.EnableCount)
responseSchema.Properties.Add(ODataConstants.OdataCount);
if (context.Settings.EnablePagination)
@@ -210,7 +211,7 @@ internal static IEnumerable GetAllCollectionEntityTypes(this
private static OpenApiSchema CreateCollectionSchema(ODataContext context, IEdmStructuredType structuredType, OpenApiDocument document)
{
- IOpenApiSchema schema = null;
+ IOpenApiSchema? schema = null;
var entityType = structuredType as IEdmEntityType;
if (context.Settings.EnableDerivedTypesReferencesForResponses && entityType != null)
@@ -315,6 +316,7 @@ public static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdm
{
IsFlags = true,
};
+ schema.Extensions ??= new Dictionary();
schema.Extensions.Add(OpenApiEnumFlagsExtension.Name, enumFlagsExtension);
}
@@ -334,12 +336,15 @@ public static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdm
AddEnumDescription(member, extension, context);
}
- if(extension?.ValuesDescriptions.Any() ?? false)
+ if(extension is {ValuesDescriptions.Count:> 0})
+ {
+ schema.Extensions ??= new Dictionary();
schema.Extensions.Add(OpenApiEnumValuesDescriptionExtension.Name, extension);
+ }
schema.Title = enumType.Name;
return schema;
}
- private static void AddEnumDescription(IEdmEnumMember member, OpenApiEnumValuesDescriptionExtension target, ODataContext context)
+ private static void AddEnumDescription(IEdmEnumMember member, OpenApiEnumValuesDescriptionExtension? target, ODataContext context)
{
if (target == null)
return;
@@ -485,12 +490,12 @@ internal static IOpenApiSchema CreateSchemaTypeSchema(this ODataContext context,
private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredType structuredType, bool processBase, bool processExample,
OpenApiDocument document,
- IEnumerable derivedTypes = null)
+ IEnumerable? derivedTypes = null)
{
Debug.Assert(context != null);
Debug.Assert(structuredType != null);
- JsonNode example = null;
+ JsonNode? example = null;
if (context.Settings.ShowSchemaExamples)
{
example = CreateStructuredTypePropertiesExample(context, structuredType, document);
@@ -504,8 +509,8 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
if (processBase && structuredType.BaseType != null)
{
// The x-ms-discriminator-value extension is added to structured types which are derived types.
- Dictionary extension = null;
- if (context.Settings.EnableDiscriminatorValue && !derivedTypes.Any())
+ Dictionary? extension = null;
+ if (context.Settings.EnableDiscriminatorValue && (derivedTypes is null || !derivedTypes.Any()))
{
extension = new Dictionary
{
@@ -537,11 +542,13 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
else
{
// The discriminator object is added to structured types which have derived types.
- OpenApiDiscriminator discriminator = null;
- if (context.Settings.EnableDiscriminatorValue && derivedTypes.Any())
+ OpenApiDiscriminator? discriminator = null;
+ if (context.Settings.EnableDiscriminatorValue && derivedTypes is not null && derivedTypes.Any())
{
Dictionary mapping = derivedTypes
- .ToDictionary(x => $"#{x.FullTypeName()}", x => new OpenApiSchemaReference(x.FullTypeName(), document).Reference.ReferenceV3);
+ .Select(x => ($"#{x.FullTypeName()}", new OpenApiSchemaReference(x.FullTypeName(), document).Reference.ReferenceV3))
+ .Where(x => x.Item2 != null)
+ .ToDictionary(x => x.Item1, x => x.Item2!);
discriminator = new OpenApiDiscriminator
{
@@ -571,13 +578,13 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
if (context.Settings.EnableDiscriminatorValue)
{
- JsonNode defaultValue = null;
+ JsonNode? defaultValue = null;
bool isBaseTypeEntity = Constants.EntityName.Equals(structuredType.BaseType?.FullTypeName().Split('.').Last(), StringComparison.OrdinalIgnoreCase);
bool isBaseTypeAbstractNonEntity = (structuredType.BaseType?.IsAbstract ?? false) && !isBaseTypeEntity;
if (!context.Settings.EnableTypeDisambiguationForDefaultValueOfOdataTypeProperty ||
isBaseTypeAbstractNonEntity ||
- context.Model.IsBaseTypeReferencedAsTypeInModel(structuredType.BaseType))
+ structuredType.BaseType is not null && context.Model.IsBaseTypeReferencedAsTypeInModel(structuredType.BaseType))
{
defaultValue = "#" + structuredType.FullTypeName();
}
@@ -591,6 +598,7 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
throw new InvalidOperationException(
$"Property {Constants.OdataType} is already present in schema {structuredType.FullTypeName()}; verify CSDL.");
}
+ schema.Required ??= new HashSet();
schema.Required.Add(Constants.OdataType);
}
@@ -629,7 +637,7 @@ internal static JsonObject CreateStructuredTypePropertiesExample(ODataContext co
if (propertyType.TypeKind() == EdmTypeKind.Primitive &&
item is JsonValue jsonValue &&
- jsonValue.TryGetValue(out string stringAny) &&
+ jsonValue.TryGetValue(out var stringAny) &&
structuredType is IEdmEntityType entityType &&
entityType.Key().Any(k => StringComparer.Ordinal.Equals(k.Name, property.Name)))
{
@@ -642,7 +650,7 @@ structuredType is IEdmEntityType entityType &&
return example;
}
- private static JsonNode GetTypeNameForPrimitive(ODataContext context, IEdmTypeReference edmTypeReference, OpenApiDocument document)
+ private static JsonNode? GetTypeNameForPrimitive(ODataContext context, IEdmTypeReference edmTypeReference, OpenApiDocument document)
{
IEdmPrimitiveType primitiveType = edmTypeReference.AsPrimitive().PrimitiveDefinition();
IOpenApiSchema schema = context.CreateSchema(primitiveType, document);
@@ -685,7 +693,7 @@ EdmTypeKind.Primitive when edmTypeReference.IsInt16() ||
edmTypeReference.IsInt64() ||
edmTypeReference.IsFloating() ||
edmTypeReference.IsDouble() => 0,
- EdmTypeKind.Primitive => GetTypeNameForPrimitive(context, edmTypeReference, document),
+ EdmTypeKind.Primitive when GetTypeNameForPrimitive(context, edmTypeReference, document) is JsonNode primitiveType => primitiveType,
EdmTypeKind.Entity or EdmTypeKind.Complex => new JsonObject()
{
@@ -700,7 +708,7 @@ EdmTypeKind.Primitive when edmTypeReference.IsInt16() ||
};
}
- private static JsonNode CreateDefault(this IEdmStructuralProperty property)
+ private static JsonNode? CreateDefault(this IEdmStructuralProperty property)
{
if (property == null ||
property.DefaultValueString == null)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs
index 3aa231f98..5a6c39257 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs
@@ -8,7 +8,6 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
-using Microsoft.OpenApi.OData.Vocabulary.Authorization;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
using Microsoft.OpenApi.Models.References;
@@ -36,12 +35,16 @@ public static IEnumerable CreateSecurityRequirements
{
foreach (PermissionType permission in permissions)
{
+ if (string.IsNullOrEmpty(permission.SchemeName))
+ {
+ continue;
+ }
yield return new OpenApiSecurityRequirement
{
[
new OpenApiSecuritySchemeReference(permission.SchemeName, document)
- ] = new List(permission.Scopes?.Select(c => c.Scope) ?? new List())
- };
+ ] = [.. permission.Scopes?.Select(c => c.Scope).OfType() ?? []]
+ };
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs
index e5156a837..5c3469351 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs
@@ -4,7 +4,6 @@
// ------------------------------------------------------------
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.OpenApi.Models;
@@ -37,6 +36,10 @@ public static void AddSecuritySchemesToDocument(this ODataContext context, OpenA
foreach (var authorization in authorizations)
{
+ if (string.IsNullOrEmpty(authorization.Name))
+ {
+ continue;
+ }
OpenApiSecurityScheme scheme = new OpenApiSecurityScheme
{
Type = authorization.SchemeType,
@@ -104,7 +107,8 @@ private static void AppendOpenIdConnect(OpenApiSecurityScheme scheme, OpenIDConn
Debug.Assert(scheme != null);
Debug.Assert(openIdConnect != null);
- scheme.OpenIdConnectUrl = new Uri(openIdConnect.IssuerUrl);
+ if (!string.IsNullOrEmpty(openIdConnect.IssuerUrl))
+ scheme.OpenIdConnectUrl = new Uri(openIdConnect.IssuerUrl);
}
private static void AppendOAuth2(OpenApiSecurityScheme scheme, OAuthAuthorization oAuth2)
@@ -113,11 +117,11 @@ private static void AppendOAuth2(OpenApiSecurityScheme scheme, OAuthAuthorizatio
Debug.Assert(oAuth2 != null);
scheme.Flows = new OpenApiOAuthFlows();
- OpenApiOAuthFlow flow = null;
+ OpenApiOAuthFlow? flow = null;
switch (oAuth2.OAuth2Type)
{
- case OAuth2Type.AuthCode: // AuthCode
- OAuth2AuthCode authCode = (OAuth2AuthCode)oAuth2;
+ case OAuth2Type.AuthCode when oAuth2 is OAuth2AuthCode {AuthorizationUrl: not null, TokenUrl: not null} authCode:
+ // AuthCode
flow = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri(authCode.AuthorizationUrl),
@@ -126,8 +130,8 @@ private static void AppendOAuth2(OpenApiSecurityScheme scheme, OAuthAuthorizatio
scheme.Flows.AuthorizationCode = flow;
break;
- case OAuth2Type.Pasword: // Password
- OAuth2Password password = (OAuth2Password)oAuth2;
+ case OAuth2Type.Password when oAuth2 is OAuth2Password { TokenUrl: not null} password:
+ // Password
flow = new OpenApiOAuthFlow
{
TokenUrl = new Uri(password.TokenUrl)
@@ -135,8 +139,8 @@ private static void AppendOAuth2(OpenApiSecurityScheme scheme, OAuthAuthorizatio
scheme.Flows.Password = flow;
break;
- case OAuth2Type.Implicit: // Implicit
- OAuth2Implicit @implicit = (OAuth2Implicit)oAuth2;
+ case OAuth2Type.Implicit when oAuth2 is OAuth2Implicit {AuthorizationUrl: not null} @implicit:
+ // Implicit
flow = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri(@implicit.AuthorizationUrl)
@@ -144,8 +148,8 @@ private static void AppendOAuth2(OpenApiSecurityScheme scheme, OAuthAuthorizatio
scheme.Flows.Implicit = flow;
break;
- case OAuth2Type.ClientCredentials: // ClientCredentials
- OAuth2ClientCredentials credentials = (OAuth2ClientCredentials)oAuth2;
+ case OAuth2Type.ClientCredentials when oAuth2 is OAuth2ClientCredentials {TokenUrl: not null} credentials:
+ // ClientCredentials
flow = new OpenApiOAuthFlow
{
TokenUrl = new Uri(credentials.TokenUrl)
@@ -155,11 +159,14 @@ private static void AppendOAuth2(OpenApiSecurityScheme scheme, OAuthAuthorizatio
}
Debug.Assert(flow != null);
- flow.RefreshUrl = new Uri(oAuth2.RefreshUrl);
+ if (!string.IsNullOrEmpty(oAuth2.RefreshUrl))
+ flow.RefreshUrl = new Uri(oAuth2.RefreshUrl);
if (oAuth2.Scopes != null)
{
- flow.Scopes = oAuth2.Scopes.ToDictionary(s => s.Scope, s => s.Description);
+ flow.Scopes = oAuth2.Scopes
+ .Where(static x => !string.IsNullOrEmpty(x.Scope) && !string.IsNullOrEmpty(x.Description))
+ .ToDictionary(s => s.Scope!, s => s.Description!);
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiTagGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiTagGenerator.cs
index c96d76952..192d2fc18 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiTagGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiTagGenerator.cs
@@ -66,7 +66,7 @@ public static ISet CreateTags(this ODataContext context)
// The tags array can contain additional Tag Objects for other logical groups,
// e.g. for action imports or function imports that are not associated with an entity set.
case EdmContainerElementKind.ActionImport: // Action Import
- OpenApiTag actionImportTag = context.CreateOperationImportTag((IEdmActionImport)element);
+ var actionImportTag = context.CreateOperationImportTag((IEdmActionImport)element);
if (actionImportTag != null)
{
tags.Add(actionImportTag);
@@ -74,7 +74,7 @@ public static ISet CreateTags(this ODataContext context)
break;
case EdmContainerElementKind.FunctionImport: // Function Import
- OpenApiTag functionImportTag = context.CreateOperationImportTag((IEdmFunctionImport)element);
+ var functionImportTag = context.CreateOperationImportTag((IEdmFunctionImport)element);
if (functionImportTag != null)
{
tags.Add(functionImportTag);
@@ -87,7 +87,7 @@ public static ISet CreateTags(this ODataContext context)
return tags;
}
- private static OpenApiTag CreateOperationImportTag(this ODataContext context, IEdmOperationImport operationImport)
+ private static OpenApiTag? CreateOperationImportTag(this ODataContext context, IEdmOperationImport operationImport)
{
Debug.Assert(context != null);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
index 7e979d2b1..f07b7c5e8 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
+++ b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
@@ -18,6 +18,7 @@
..\..\bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml
true
+ enable
README.md
@@ -30,11 +31,11 @@
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs
index 679a0bdfb..64b6878ab 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs
@@ -21,7 +21,7 @@ internal static class IEdmExpressionExtensions
///
/// The .
/// The null or .
- public static ODataValue Convert(this IEdmExpression expression)
+ public static ODataValue? Convert(this IEdmExpression expression)
{
if (expression == null)
{
@@ -112,7 +112,7 @@ public static ODataValue Convert(this IEdmExpression expression)
return new ODataResourceValue
{
TypeReference = recordExpression.DeclaredType,
- Properties = recordExpression.Properties.ToDictionary(p => p.Name, p => p.Value.Convert())
+ Properties = recordExpression.Properties.Select(p => (p.Name, p.Value.Convert())).Where(p => p.Item2 is not null).ToDictionary(p => p.Item1, p => p.Item2!)
};
case EdmExpressionKind.Collection:
@@ -122,7 +122,7 @@ public static ODataValue Convert(this IEdmExpression expression)
TypeReference = collectionExpression.DeclaredType
};
- collectionValue.Elements = collectionExpression.Elements.Select(e => e.Convert()).ToList();
+ collectionValue.Elements = collectionExpression.Elements.Select(e => e.Convert()).OfType().ToList();
return collectionValue;
case EdmExpressionKind.Path:
diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/ODataCollectValue.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataCollectValue.cs
index a0c27e8d9..c78378286 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OData/ODataCollectValue.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataCollectValue.cs
@@ -12,6 +12,6 @@ namespace Microsoft.OpenApi.OData
///
internal class ODataCollectValue : ODataValue
{
- public IList Elements { get; set; }
+ public IList? Elements { get; set; }
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/ODataPrimitiveValue.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataPrimitiveValue.cs
index 4bab519d5..24a616723 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OData/ODataPrimitiveValue.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataPrimitiveValue.cs
@@ -20,7 +20,7 @@ public ODataPrimitiveValue(object value)
///
public object Value { get; private set; }
- public override string ToString()
+ public override string? ToString()
{
return Value.ToString();
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/ODataResourceValue.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataResourceValue.cs
index c0990e097..c22f731e6 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OData/ODataResourceValue.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataResourceValue.cs
@@ -15,6 +15,6 @@ internal class ODataResourceValue : ODataValue
///
/// Gets or sets the properties.
///
- public IDictionary Properties { get; set; }
+ public IDictionary? Properties { get; set; }
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/ODataValue.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataValue.cs
index d51c0173a..ee8e6bf93 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OData/ODataValue.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataValue.cs
@@ -15,6 +15,6 @@ internal abstract class ODataValue
///
/// Gets or set the type reference of this value.
///
- public IEdmTypeReference TypeReference { get; set; }
+ public IEdmTypeReference? TypeReference { get; set; }
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
index ecb73a7d4..5615f3ff0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
@@ -138,7 +138,7 @@ public class OpenApiConvertSettings
///
/// Gets/sets a value that specifies a prefix to be prepended to all generated paths.
///
- public string PathPrefix
+ public string? PathPrefix
{
get
{
@@ -166,7 +166,7 @@ public string PathPrefix
///
/// Gets/sets a route path prefix provider.
///
- public IODataRoutePathPrefixProvider RoutePathPrefixProvider { get; set; }
+ public IODataRoutePathPrefixProvider? RoutePathPrefixProvider { get; set; }
///
/// Gets/Sets a value indicating whether or not to show the OpenAPI links in the responses.
@@ -203,7 +203,7 @@ public string PathPrefix
///
/// Gets/sets a the path provider.
///
- public IODataPathProvider PathProvider { get; set; }
+ public IODataPathProvider? PathProvider { get; set; }
///
/// Gets/sets a value indicating whether or not add OData $count segments in the description for collections.
@@ -315,7 +315,7 @@ public string PathPrefix
///
/// The namespace prefix to be stripped from the in method paths.
///
- public string NamespacePrefixToStripForInMethodPaths { get; set; }
+ public string? NamespacePrefixToStripForInMethodPaths { get; set; }
///
/// Enables the use of aliases for the type cast segments to shorten the url path.
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs
index 79843b934..57dc7accc 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs
@@ -23,7 +23,7 @@ protected ComplexPropertyBaseOperationHandler(OpenApiDocument document) : base(d
{
}
- protected ODataComplexPropertySegment ComplexPropertySegment;
+ protected ODataComplexPropertySegment? ComplexPropertySegment;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -35,15 +35,18 @@ protected override void Initialize(ODataContext context, ODataPath path)
///
protected override void SetTags(OpenApiOperation operation)
{
- string tagName = EdmModelHelper.GenerateComplexPropertyPathTagName(Path, Context);
- operation.Tags ??= new HashSet();
- if (!string.IsNullOrEmpty(tagName))
+ if (Context is not null && Path is not null)
{
- Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
- {
- Name = tagName
- });
- operation.Tags.Add(new OpenApiTagReference(tagName, _document));
+ string tagName = EdmModelHelper.GenerateComplexPropertyPathTagName(Path, Context);
+ operation.Tags ??= new HashSet();
+ if (!string.IsNullOrEmpty(tagName))
+ {
+ Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = tagName
+ });
+ operation.Tags.Add(new OpenApiTagReference(tagName, _document));
+ }
}
base.SetTags(operation);
@@ -52,10 +55,10 @@ protected override void SetTags(OpenApiOperation operation)
///
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs)
+ if (Context is {Settings.ShowExternalDocs: true} && CustomLinkRel is not null)
{
- var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(ComplexPropertySegment.Property, CustomLinkRel);
+ var externalDocs = (string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetLinkRecord(TargetPath, CustomLinkRel)) ??
+ (ComplexPropertySegment is null ? null : Context.Model.GetLinkRecord(ComplexPropertySegment.Property, CustomLinkRel));
if (externalDocs != null)
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs
index 6e873c83c..51db8e26c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs
@@ -3,11 +3,13 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
@@ -31,32 +33,37 @@ public ComplexPropertyGetOperationHandler(OpenApiDocument document):base(documen
///
public override HttpMethod OperationType => HttpMethod.Get;
- private ReadRestrictionsType _readRestrictions;
+ private ReadRestrictionsType? _readRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- var complexPropertyReadRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.ReadRestrictions);
- _readRestrictions?.MergePropertiesIfNull(complexPropertyReadRestrictions);
- _readRestrictions ??= complexPropertyReadRestrictions;
+ _readRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+
+ if (ComplexPropertySegment is not null)
+ {
+ var complexPropertyReadRestrictions = Context?.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.ReadRestrictions);
+ _readRestrictions?.MergePropertiesIfNull(complexPropertyReadRestrictions);
+ _readRestrictions ??= complexPropertyReadRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && Path is not null)
{
- string prefix = ComplexPropertySegment.Property.Type.IsCollection() ? "List" : "Get";
+ string prefix = ComplexPropertySegment is not null && ComplexPropertySegment.Property.Type.IsCollection() ? "List" : "Get";
operation.OperationId = EdmModelHelper.GenerateComplexPropertyPathOperationId(Path, Context, prefix);
}
// Summary and Description
- string placeHolder = $"Get {ComplexPropertySegment.Property.Name} property value";
+ string placeHolder = $"Get {ComplexPropertySegment?.Property.Name} property value";
operation.Summary = _readRestrictions?.Description ?? placeHolder;
- operation.Description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(ComplexPropertySegment.Property);
+ operation.Description = _readRestrictions?.LongDescription ??
+ (ComplexPropertySegment is null ? null : Context?.Model.GetDescriptionAnnotation(ComplexPropertySegment.Property));
base.SetBasicInfo(operation);
}
@@ -65,7 +72,10 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- IOpenApiParameter parameter;
+ if (Context is null || ComplexPropertySegment is null) return;
+
+ IOpenApiParameter? parameter;
+ operation.Parameters ??= [];
if(ComplexPropertySegment.Property.Type.IsCollection())
{
// The parameters array contains Parameter Objects for all system query options allowed for this collection,
@@ -73,35 +83,35 @@ protected override void SetParameters(OpenApiOperation operation)
// Capabilities.TopSupported, Capabilities.SkipSupported, Capabilities.SearchRestrictions,
// Capabilities.FilterRestrictions, and Capabilities.CountRestrictions
// $top
- parameter = Context.CreateTop(TargetPath, _document) ?? Context.CreateTop(ComplexPropertySegment.Property, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateTop(TargetPath, _document)) ?? Context.CreateTop(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $skip
- parameter = Context.CreateSkip(TargetPath, _document) ?? Context.CreateSkip(ComplexPropertySegment.Property, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSkip(TargetPath, _document)) ?? Context.CreateSkip(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $search
- parameter = Context.CreateSearch(TargetPath, _document) ?? Context.CreateSearch(ComplexPropertySegment.Property, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSearch(TargetPath, _document)) ?? Context.CreateSearch(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $filter
- parameter = Context.CreateFilter(TargetPath, _document) ?? Context.CreateFilter(ComplexPropertySegment.Property, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateFilter(TargetPath, _document)) ?? Context.CreateFilter(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $count
- parameter = Context.CreateCount(TargetPath, _document) ?? Context.CreateCount(ComplexPropertySegment.Property, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateCount(TargetPath, _document)) ?? Context.CreateCount(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -112,40 +122,49 @@ protected override void SetParameters(OpenApiOperation operation)
// of just providing a comma-separated list of properties can be expressed via an array-valued
// parameter with an enum constraint
// $order
- parameter = Context.CreateOrderBy(TargetPath, ComplexPropertySegment.ComplexType)
- ?? Context.CreateOrderBy(ComplexPropertySegment.Property, ComplexPropertySegment.ComplexType);
- if (parameter != null)
+ if (ComplexPropertySegment.ComplexType is not null)
{
- operation.Parameters.Add(parameter);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateOrderBy(TargetPath, ComplexPropertySegment.ComplexType))
+ ?? Context.CreateOrderBy(ComplexPropertySegment.Property, ComplexPropertySegment.ComplexType);
+ if (parameter != null)
+ {
+ operation.Parameters.Add(parameter);
+ }
}
}
- // $select
- parameter = Context.CreateSelect(TargetPath, ComplexPropertySegment.ComplexType)
- ?? Context.CreateSelect(ComplexPropertySegment.Property, ComplexPropertySegment.ComplexType);
- if (parameter != null)
+ if (ComplexPropertySegment.ComplexType is not null)
{
- operation.Parameters.Add(parameter);
- }
+ // $select
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSelect(TargetPath, ComplexPropertySegment.ComplexType))
+ ?? Context.CreateSelect(ComplexPropertySegment.Property, ComplexPropertySegment.ComplexType);
+ if (parameter != null)
+ {
+ operation.Parameters.Add(parameter);
+ }
- // $expand
- parameter = Context.CreateExpand(TargetPath, ComplexPropertySegment.ComplexType)
- ?? Context.CreateExpand(ComplexPropertySegment.Property, ComplexPropertySegment.ComplexType);
- if (parameter != null)
- {
- operation.Parameters.Add(parameter);
+ // $expand
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateExpand(TargetPath, ComplexPropertySegment.ComplexType))
+ ?? Context.CreateExpand(ComplexPropertySegment.Property, ComplexPropertySegment.ComplexType);
+ if (parameter != null)
+ {
+ operation.Parameters.Add(parameter);
+ }
}
}
protected override void SetExtensions(OpenApiOperation operation)
{
- if (Context.Settings.EnablePagination && ComplexPropertySegment.Property.Type.IsCollection())
+ if (Context is {Settings.EnablePagination: true} &&
+ ComplexPropertySegment is not null &&
+ ComplexPropertySegment.Property.Type.IsCollection())
{
JsonObject extension = new()
{
{ "nextLinkName", "@odata.nextLink"},
{ "operationName", Context.Settings.PageableOperationName}
};
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
base.SetExtensions(operation);
@@ -154,18 +173,20 @@ protected override void SetExtensions(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- if (ComplexPropertySegment.Property.Type.IsCollection())
- {
- SetCollectionResponse(operation, ComplexPropertySegment.ComplexType.FullName());
- }
- else
- {
- var schema = new OpenApiSchemaReference(ComplexPropertySegment.ComplexType.FullName(), _document);
+ if (ComplexPropertySegment is not null)
+ if (ComplexPropertySegment.Property.Type.IsCollection())
+ {
+ SetCollectionResponse(operation, ComplexPropertySegment.ComplexType.FullName());
+ }
+ else
+ {
+ var schema = new OpenApiSchemaReference(ComplexPropertySegment.ComplexType.FullName(), _document);
- SetSingleResponse(operation, schema);
- }
+ SetSingleResponse(operation, schema);
+ }
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -176,7 +197,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs
index a6734b032..2bb2e2cf0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs
@@ -31,32 +31,36 @@ public ComplexPropertyPostOperationHandler(OpenApiDocument document):base(docume
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- if (!ComplexPropertySegment.Property.Type.IsCollection())
+ if (ComplexPropertySegment is null || !ComplexPropertySegment.Property.Type.IsCollection())
{
throw new InvalidOperationException("OData conventions do not support POSTing to a complex property that is not a collection.");
}
- _insertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
- var complexPropertyInsertRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.InsertRestrictions);
+ if (!string.IsNullOrEmpty(TargetPath))
+ {
+ _insertRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
+ }
+
+ var complexPropertyInsertRestrictions = Context?.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.InsertRestrictions);
_insertRestrictions?.MergePropertiesIfNull(complexPropertyInsertRestrictions);
_insertRestrictions ??= complexPropertyInsertRestrictions;
}
///
public override HttpMethod OperationType => HttpMethod.Post;
- private InsertRestrictionsType _insertRestrictions;
+ private InsertRestrictionsType? _insertRestrictions;
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && Path is not null)
{
operation.OperationId = EdmModelHelper.GenerateComplexPropertyPathOperationId(Path, Context, "Set");
}
// Summary and Description
- string placeHolder = $"Sets a new value for the collection of {ComplexPropertySegment.ComplexType.Name}.";
+ string placeHolder = $"Sets a new value for the collection of {ComplexPropertySegment?.ComplexType?.Name}.";
operation.Summary = _insertRestrictions?.Description ?? placeHolder;
operation.Description = _insertRestrictions?.LongDescription;
@@ -68,6 +72,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ operation.Parameters ??= [];
operation.Parameters.Add(new OpenApiParameter
{
Name = "If-Match",
@@ -102,7 +107,8 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
base.SetResponses(operation);
}
@@ -113,7 +119,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_insertRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -134,8 +140,9 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
}
}
- private OpenApiSchema GetOpenApiSchema()
+ private OpenApiSchema? GetOpenApiSchema()
{
+ if (ComplexPropertySegment is null) return null;
return new()
{
Type = JsonSchemaType.Array,
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs
index 1ac6ce8da..59532cf66 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs
@@ -28,28 +28,33 @@ protected ComplexPropertyUpdateOperationHandler(OpenApiDocument document) : base
}
- private UpdateRestrictionsType _updateRestrictions;
+ private UpdateRestrictionsType? _updateRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
- var complexPropertyUpdateRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.UpdateRestrictions);
- _updateRestrictions?.MergePropertiesIfNull(complexPropertyUpdateRestrictions);
- _updateRestrictions ??= complexPropertyUpdateRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _updateRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+
+ if (ComplexPropertySegment is not null)
+ {
+ var complexPropertyUpdateRestrictions = Context?.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.UpdateRestrictions);
+ _updateRestrictions?.MergePropertiesIfNull(complexPropertyUpdateRestrictions);
+ _updateRestrictions ??= complexPropertyUpdateRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = $"Update property {ComplexPropertySegment.Property.Name} value.";
+ string placeHolder = $"Update property {ComplexPropertySegment?.Property.Name} value.";
operation.Summary = _updateRestrictions?.Description ?? placeHolder;
operation.Description = _updateRestrictions?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && Path is not null)
{
string prefix = OperationType == HttpMethod.Patch ? "Update" : "Set";
operation.OperationId = EdmModelHelper.GenerateComplexPropertyPathOperationId(Path, Context, prefix);
@@ -80,7 +85,8 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
base.SetResponses(operation);
}
protected override void SetSecurity(OpenApiOperation operation)
@@ -90,7 +96,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -111,8 +117,9 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
}
}
- private IOpenApiSchema GetOpenApiSchema()
+ private IOpenApiSchema? GetOpenApiSchema()
{
+ if (ComplexPropertySegment is null) return null;
var schema = new OpenApiSchemaReference(ComplexPropertySegment.ComplexType.FullName(), _document);
if (ComplexPropertySegment.Property.Type.IsCollection())
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs
index 0f7620d63..96b6e773d 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs
@@ -11,7 +11,6 @@
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
@@ -40,8 +39,8 @@ public DollarCountGetOperationHandler(OpenApiDocument document) : base(document)
/// Gets/sets the segment before $count.
/// this segment could be "entity set", "Collection property", "Composable function whose return is collection",etc.
///
- internal ODataSegment SecondLastSegment { get; set; }
- private ODataSegment firstSegment;
+ internal ODataSegment? SecondLastSegment { get; set; }
+ private ODataSegment? firstSegment;
private int pathCount;
private const int SecondLastSegmentIndex = 2;
private readonly List annotatables = [];
@@ -61,19 +60,19 @@ protected override void Initialize(ODataContext context, ODataPath path)
AddODataSegmentToAnnotables(SecondLastSegment, path.Segments.Count > SecondLastSegmentIndex ? path.Segments.SkipLast(SecondLastSegmentIndex).ToArray() : []);
}
- private void AddODataSegmentToAnnotables(ODataSegment oDataSegment, ODataSegment[] oDataSegments)
+ private void AddODataSegmentToAnnotables(ODataSegment? oDataSegment, ODataSegment[] oDataSegments)
{
- if (oDataSegment is ODataNavigationSourceSegment sourceSegment)
+ if (oDataSegment is ODataNavigationSourceSegment {NavigationSource: IEdmEntitySet sourceSet})
{
- annotatables.Add(sourceSegment.NavigationSource as IEdmEntitySet);
+ annotatables.Add(sourceSet);
}
else if (oDataSegment is ODataNavigationPropertySegment navigationPropertySegment)
{
annotatables.Add(navigationPropertySegment.NavigationProperty);
}
- else if (oDataSegment is ODataTypeCastSegment odataTypeCastSegment)
+ else if (oDataSegment is ODataTypeCastSegment {StructuredType: IEdmVocabularyAnnotatable annotable})
{
- annotatables.Add(odataTypeCastSegment.StructuredType as IEdmVocabularyAnnotatable);
+ annotatables.Add(annotable);
if (annotatables.Count == 1 && oDataSegments.Length > 0)
{// we want to look at the parent navigation property or entity set
AddODataSegmentToAnnotables(oDataSegments[oDataSegments.Length - 1], oDataSegments.SkipLast(1).ToArray());
@@ -84,7 +83,7 @@ private void AddODataSegmentToAnnotables(ODataSegment oDataSegment, ODataSegment
///
protected override void SetTags(OpenApiOperation operation)
{
- string tagName = null;
+ string? tagName = null;
operation.Tags ??= new HashSet();
if (SecondLastSegment is ODataNavigationSourceSegment sourceSegment)
@@ -95,7 +94,7 @@ protected override void SetTags(OpenApiOperation operation)
{
tagName = TagNameFromNavigationPropertySegment();
}
- else if (SecondLastSegment is ODataTypeCastSegment)
+ else if (SecondLastSegment is ODataTypeCastSegment && Path is not null)
{
ODataSegment lastThirdSegment = Path.Segments[pathCount - 3];
if (lastThirdSegment is ODataNavigationSourceSegment sourceSegment2)
@@ -107,12 +106,12 @@ protected override void SetTags(OpenApiOperation operation)
tagName = TagNameFromNavigationPropertySegment();
}
}
- else if (SecondLastSegment is ODataComplexPropertySegment)
+ else if (SecondLastSegment is ODataComplexPropertySegment && Path is not null && Context is not null)
{
tagName = EdmModelHelper.GenerateComplexPropertyPathTagName(Path, Context);
}
- if (tagName != null)
+ if (tagName != null && Context is not null)
{
Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
{
@@ -127,9 +126,9 @@ string TagNameFromNavigationSourceSegment(ODataNavigationSourceSegment sourceSeg
return $"{sourceSegment.NavigationSource.Name}.{sourceSegment.NavigationSource.EntityType.Name}";
}
- string TagNameFromNavigationPropertySegment()
+ string? TagNameFromNavigationPropertySegment()
{
- return EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context);
+ return Path is null || Context is null ? null : EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context);
}
base.SetTags(operation);
@@ -142,9 +141,9 @@ protected override void SetBasicInfo(OpenApiOperation operation)
operation.Summary = $"Get the number of the resource";
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && Path is not null)
{
- if (SecondLastSegment is ODataNavigationSourceSegment)
+ if (SecondLastSegment is ODataNavigationSourceSegment && firstSegment is not null)
{
operation.OperationId = $"{firstSegment.Identifier}.GetCount-{Path.GetPathHash(Context.Settings)}";
}
@@ -153,9 +152,8 @@ protected override void SetBasicInfo(OpenApiOperation operation)
var navPropOpId = string.Join(".", EdmModelHelper.RetrieveNavigationPropertyPathsOperationIdSegments(Path, Context));
operation.OperationId = $"{navPropOpId}.GetCount-{Path.GetPathHash(Context.Settings)}";
}
- else if (SecondLastSegment is ODataTypeCastSegment odataTypeCastSegment)
+ else if (SecondLastSegment is ODataTypeCastSegment { StructuredType: IEdmNamedElement targetStructuredType})
{
- IEdmNamedElement targetStructuredType = odataTypeCastSegment.StructuredType as IEdmNamedElement;
operation.OperationId = $"{EdmModelHelper.GenerateODataTypeCastPathOperationIdPrefix(Path, Context, false)}.GetCount.As{Utils.UpperFirstChar(targetStructuredType.Name)}-{Path.GetPathHash(Context.Settings)}";
}
else if (SecondLastSegment is ODataComplexPropertySegment)
@@ -173,11 +171,12 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponseReference(Constants.DollarCountSchemaName, _document)
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -187,27 +186,30 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- IOpenApiParameter parameter;
- parameter = Context.CreateSearch(TargetPath, _document) ?? (annotatables.Count == 0 ? null : annotatables.Select(x => Context.CreateSearch(x, _document)).FirstOrDefault(static x => x is not null));
+ var parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context?.CreateSearch(TargetPath, _document)) ??
+ (annotatables.Count == 0 ? null : annotatables.Select(x => Context?.CreateSearch(x, _document)).FirstOrDefault(static x => x is not null));
if (parameter != null)
{
+ operation.Parameters ??= [];
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateFilter(TargetPath, _document) ?? (annotatables.Count == 0 ? null : annotatables.Select(x => Context.CreateFilter(x, _document)).FirstOrDefault(static x => x is not null));
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context?.CreateFilter(TargetPath, _document)) ??
+ (annotatables.Count == 0 ? null : annotatables.Select(x => Context?.CreateFilter(x, _document)).FirstOrDefault(static x => x is not null));
if (parameter != null)
{
+ operation.Parameters ??= [];
operation.Parameters.Add(parameter);
}
}
protected override void AppendCustomParameters(OpenApiOperation operation)
{
- ReadRestrictionsType readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- if (annotatables.Count > 0)
+ var readRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (annotatables.Count > 0 && Context is not null)
{
- ReadRestrictionsType annotatableReadRestrictions = annotatables.Select(x => Context.Model.GetRecord(x, CapabilitiesConstants.ReadRestrictions)).FirstOrDefault(static x => x is not null);
+ var annotatableReadRestrictions = annotatables.Select(x => Context.Model.GetRecord(x, CapabilitiesConstants.ReadRestrictions)).FirstOrDefault(static x => x is not null);
readRestrictions?.MergePropertiesIfNull(annotatableReadRestrictions);
readRestrictions ??= annotatableReadRestrictions;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
index 4111f9ddf..f5b94190f 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
@@ -3,9 +3,11 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System.Collections.Generic;
using System.Net.Http;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Generator;
@@ -30,11 +32,10 @@ public EdmActionImportOperationHandler(OpenApiDocument document):base(document)
protected override void SetRequestBody(OpenApiOperation operation)
{
- IEdmActionImport actionImport = EdmOperationImport as IEdmActionImport;
-
// The requestBody field contains a Request Body Object describing the structure of the request body.
// Its schema value follows the rules for Schema Objects for complex types, with one property per action parameter.
- operation.RequestBody = Context.CreateRequestBody(actionImport, _document);
+ if (EdmOperationImport is IEdmActionImport actionImport)
+ operation.RequestBody = Context?.CreateRequestBody(actionImport, _document);
base.SetRequestBody(operation);
}
@@ -42,6 +43,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("actionImport"));
base.SetExtensions(operation);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs
index 057147b30..0aed94706 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs
@@ -3,9 +3,11 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System.Collections.Generic;
using System.Net.Http;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
@@ -36,10 +38,14 @@ protected override void SetBasicInfo(OpenApiOperation operation)
{
base.SetBasicInfo(operation);
- InsertRestrictionsType insertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
- InsertRestrictionsType operationReadRestrictions = Context.Model.GetRecord(EdmOperation, CapabilitiesConstants.InsertRestrictions);
- insertRestrictions?.MergePropertiesIfNull(operationReadRestrictions);
- insertRestrictions ??= operationReadRestrictions;
+ var insertRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
+
+ if (Context is not null && EdmOperation is not null)
+ {
+ var operationReadRestrictions = Context?.Model.GetRecord(EdmOperation, CapabilitiesConstants.InsertRestrictions);
+ insertRestrictions?.MergePropertiesIfNull(operationReadRestrictions);
+ insertRestrictions ??= operationReadRestrictions;
+ }
// Description
if (!string.IsNullOrWhiteSpace(insertRestrictions?.LongDescription))
@@ -51,7 +57,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetRequestBody(OpenApiOperation operation)
{
- if (EdmOperation is IEdmAction action && Context.CreateRequestBody(action, _document) is OpenApiRequestBody requestBody)
+ if (EdmOperation is IEdmAction action && Context?.CreateRequestBody(action, _document) is OpenApiRequestBody requestBody)
{
if (Context.Model.OperationTargetsMultiplePaths(action))
{
@@ -69,6 +75,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("action"));
base.SetExtensions(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
index 50ec9a9f5..5c6e6c6a0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
@@ -3,9 +3,11 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System.Collections.Generic;
using System.Net.Http;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Generator;
@@ -38,18 +40,21 @@ protected override void SetParameters(OpenApiOperation operation)
return;
}
- if (OperationImportSegment.ParameterMappings != null)
+ if (OperationImportSegment?.ParameterMappings != null &&
+ Context?.CreateParameters(functionImport.Function, _document, OperationImportSegment.ParameterMappings) is {} functionParamMappings)
{
- foreach (var param in Context.CreateParameters(functionImport.Function, _document, OperationImportSegment.ParameterMappings))
+ operation.Parameters ??= [];
+ foreach (var param in functionParamMappings)
{
operation.Parameters.AppendParameter(param);
}
}
- else
+ else if (Context?.CreateParameters(functionImport, _document) is {} functionParams)
{
+ operation.Parameters ??= [];
//The parameters array contains a Parameter Object for each parameter of the function overload,
// and it contains specific Parameter Objects for the allowed system query options.
- foreach (var param in Context.CreateParameters(functionImport, _document))
+ foreach (var param in functionParams)
{
operation.Parameters.AppendParameter(param);
}
@@ -59,6 +64,7 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("functionImport"));
base.SetExtensions(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
index 802ccbbf4..bbe0c4bb5 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
@@ -3,9 +3,11 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System.Collections.Generic;
using System.Net.Http;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
@@ -32,17 +34,21 @@ public EdmFunctionOperationHandler(OpenApiDocument document):base(document)
///
/// Gets the Edm Function.
///
- public IEdmFunction Function => EdmOperation as IEdmFunction;
+ public IEdmFunction? Function => EdmOperation as IEdmFunction;
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
base.SetBasicInfo(operation);
- ReadRestrictionsType readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- ReadRestrictionsType operationReadRestrictions = Context.Model.GetRecord(EdmOperation, CapabilitiesConstants.ReadRestrictions);
- readRestrictions?.MergePropertiesIfNull(operationReadRestrictions);
- readRestrictions ??= operationReadRestrictions;
+ var readRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+
+ if (Context is not null && EdmOperation is not null)
+ {
+ var operationReadRestrictions = Context.Model.GetRecord(EdmOperation, CapabilitiesConstants.ReadRestrictions);
+ readRestrictions?.MergePropertiesIfNull(operationReadRestrictions);
+ readRestrictions ??= operationReadRestrictions;
+ }
// Description
if (!string.IsNullOrWhiteSpace(readRestrictions?.LongDescription))
@@ -54,6 +60,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("function"));
base.SetExtensions(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs
index d158e0654..b537b0b62 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs
@@ -8,6 +8,7 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
@@ -31,17 +32,17 @@ protected EdmOperationImportOperationHandler(OpenApiDocument document):base(docu
{
}
- private OperationRestrictionsType _operationRestriction;
+ private OperationRestrictionsType? _operationRestriction;
///
/// Gets the .
///
- protected IEdmOperationImport EdmOperationImport { get; private set; }
+ protected IEdmOperationImport? EdmOperationImport { get; private set; }
///
/// Gets the .
///
- protected ODataOperationImportSegment OperationImportSegment { get; private set; }
+ protected ODataOperationImportSegment? OperationImportSegment { get; private set; }
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -49,29 +50,34 @@ protected override void Initialize(ODataContext context, ODataPath path)
base.Initialize(context, path);
OperationImportSegment = path.LastSegment as ODataOperationImportSegment;
- EdmOperationImport = OperationImportSegment.OperationImport;
+ EdmOperationImport = OperationImportSegment?.OperationImport;
- _operationRestriction = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.OperationRestrictions);
- var operationRestrictions = Context.Model.GetRecord(EdmOperationImport, CapabilitiesConstants.OperationRestrictions);
-
- if (_operationRestriction == null)
- {
- _operationRestriction = operationRestrictions;
- }
- else
+ _operationRestriction = string.IsNullOrEmpty(TargetPath) ? null : Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.OperationRestrictions);
+
+
+ if (EdmOperationImport is not null && Context?.Model.GetRecord(EdmOperationImport, CapabilitiesConstants.OperationRestrictions) is {} operationRestrictions)
{
- _operationRestriction.MergePropertiesIfNull(operationRestrictions);
+ if (_operationRestriction == null)
+ {
+ _operationRestriction = operationRestrictions;
+ }
+ else
+ {
+ _operationRestriction.MergePropertiesIfNull(operationRestrictions);
+ }
}
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
- operation.Summary = "Invoke " + (EdmOperationImport.IsActionImport() ? "actionImport " : "functionImport ") + EdmOperationImport.Name;
+ operation.Summary = "Invoke " + (EdmOperationImport.IsActionImport() ? "actionImport " : "functionImport ") + EdmOperationImport?.Name;
- operation.Description = Context.Model.GetDescriptionAnnotation(TargetPath) ?? Context.Model.GetDescriptionAnnotation(EdmOperationImport);
+ if (Context is not null)
+ operation.Description = (string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetDescriptionAnnotation(TargetPath)) ??
+ Context.Model.GetDescriptionAnnotation(EdmOperationImport);
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && EdmOperationImport is not null )
{
if (EdmOperationImport.IsActionImport())
{
@@ -81,7 +87,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
{
if (Context.Model.IsOperationImportOverload(EdmOperationImport))
{
- operation.OperationId = "FunctionImport." + EdmOperationImport.Name + "-" + Path.LastSegment.GetPathHash(Context.Settings);
+ operation.OperationId = "FunctionImport." + EdmOperationImport.Name + "-" + Path?.LastSegment?.GetPathHash(Context.Settings);
}
else
{
@@ -100,7 +106,9 @@ protected override void SetResponses(OpenApiOperation operation)
// describing the structure of the success response by referencing an appropriate schema
// in the global schemas. In addition, it contains a default name/value pair for
// the OData error response referencing the global responses.
- operation.Responses = Context.CreateResponses(EdmOperationImport, _document);
+
+ if (Context is not null && EdmOperationImport is not null)
+ operation.Responses = Context.CreateResponses(EdmOperationImport, _document);
base.SetResponses(operation);
}
@@ -113,7 +121,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_operationRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_operationRestriction.Permissions, _document).ToList();
}
///
@@ -138,12 +146,16 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
///
protected override void SetTags(OpenApiOperation operation)
{
- var tag = CreateTag(EdmOperationImport);
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiAny("container"));
- Context.AppendTag(tag);
+ if (EdmOperationImport is not null)
+ {
+ var tag = CreateTag(EdmOperationImport);
+ tag.Extensions ??= new Dictionary();
+ tag.Extensions.Add(Constants.xMsTocType, new OpenApiAny("container"));
+ Context?.AppendTag(tag);
- operation.Tags ??= new HashSet();
- operation.Tags.Add(new OpenApiTagReference(tag.Name, _document));
+ operation.Tags ??= new HashSet();
+ operation.Tags.Add(new OpenApiTagReference(tag.Name!, _document));
+ }
base.SetTags(operation);
}
@@ -172,10 +184,10 @@ internal static string PathAsString(IEnumerable path)
///
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs)
+ if (Context is {Settings.ShowExternalDocs: true} && CustomLinkRel is not null)
{
- var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(EdmOperationImport, CustomLinkRel);
+ var externalDocs = (string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetLinkRecord(TargetPath, CustomLinkRel)) ??
+ (EdmOperationImport is null ? null : Context.Model.GetLinkRecord(EdmOperationImport, CustomLinkRel));
if (externalDocs != null)
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs
index cfc186195..bcc644713 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs
@@ -3,11 +3,13 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
@@ -31,22 +33,22 @@ protected EdmOperationOperationHandler(OpenApiDocument document) : base(document
{
}
- private OperationRestrictionsType _operationRestriction;
+ private OperationRestrictionsType? _operationRestriction;
///
/// Gets the navigation source.
///
- protected IEdmNavigationSource NavigationSource { get; private set; }
+ protected IEdmNavigationSource? NavigationSource { get; private set; }
///
/// Gets the Edm operation.
///
- protected IEdmOperation EdmOperation { get; private set; }
+ protected IEdmOperation? EdmOperation { get; private set; }
///
/// Gets the OData operation segment.
///
- protected ODataOperationSegment OperationSegment { get; private set; }
+ protected ODataOperationSegment? OperationSegment { get; private set; }
///
/// Gets a value indicating whether the path has type cast segment or not.
@@ -59,31 +61,38 @@ protected override void Initialize(ODataContext context, ODataPath path)
base.Initialize(context, path);
// It's bound operation, the first segment must be the navigaiton source.
- ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
- NavigationSource = navigationSourceSegment.NavigationSource;
+ if (path.FirstSegment is ODataNavigationSourceSegment navigationSourceSegment)
+ NavigationSource = navigationSourceSegment.NavigationSource;
- OperationSegment = path.LastSegment as ODataOperationSegment;
- EdmOperation = OperationSegment.Operation;
+ if (path.LastSegment is ODataOperationSegment opSegment)
+ {
+ OperationSegment = opSegment;
+ EdmOperation = opSegment.Operation;
+ }
HasTypeCast = path.Segments.Any(s => s is ODataTypeCastSegment);
- _operationRestriction = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.OperationRestrictions);
- var operationRestrictions = Context.Model.GetRecord(EdmOperation, CapabilitiesConstants.OperationRestrictions);
- _operationRestriction?.MergePropertiesIfNull(operationRestrictions);
- _operationRestriction ??= operationRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _operationRestriction = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.OperationRestrictions);
+ if (Context is not null && EdmOperation is not null &&
+ Context.Model.GetRecord(EdmOperation, CapabilitiesConstants.OperationRestrictions) is { } operationRestrictions)
+ {
+ _operationRestriction?.MergePropertiesIfNull(operationRestrictions);
+ _operationRestriction ??= operationRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary
- operation.Summary = "Invoke " + (EdmOperation.IsAction() ? "action " : "function ") + EdmOperation.Name;
+ operation.Summary = "Invoke " + (EdmOperation?.IsAction() ?? false ? "action " : "function ") + EdmOperation?.Name;
// Description
- operation.Description = Context.Model.GetDescriptionAnnotation(TargetPath) ?? Context.Model.GetDescriptionAnnotation(EdmOperation);
+ operation.Description = (string.IsNullOrEmpty(TargetPath) ? null :Context?.Model.GetDescriptionAnnotation(TargetPath)) ?? Context?.Model.GetDescriptionAnnotation(EdmOperation);
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && Path is not null)
{
// When the key segment is available,
// its EntityType name will be used
@@ -96,7 +105,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
{
if (segment is ODataKeySegment keySegment)
{
- if (!keySegment.IsAlternateKey)
+ if (!keySegment.IsAlternateKey && segment is {EntityType: not null})
{
identifiers.Add(segment.EntityType.Name);
continue;
@@ -112,7 +121,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
identifiers.Add(keySegment.Identifier);
}
}
- else if (segment is ODataOperationSegment opSegment)
+ else if (segment is ODataOperationSegment {Identifier: not null} opSegment)
{
if (opSegment.Operation is IEdmFunction function && Context.Model.IsOperationOverload(function))
{
@@ -122,9 +131,9 @@ protected override void SetBasicInfo(OpenApiOperation operation)
: (pathHash + opSegment.GetPathHash(Context.Settings)).GetHashSHA256()[..4];
}
- identifiers.Add(segment.Identifier);
+ identifiers.Add(opSegment.Identifier);
}
- else
+ else if (!string.IsNullOrEmpty(segment.Identifier))
{
identifiers.Add(segment.Identifier);
}
@@ -153,11 +162,12 @@ protected override void SetTags(OpenApiOperation operation)
{
Name = tagName,
};
+ tag.Extensions ??= new Dictionary();
tag.Extensions.Add(Constants.xMsTocType, new OpenApiAny("container"));
operation.Tags ??= new HashSet();
operation.Tags.Add(new OpenApiTagReference(tag.Name, _document));
- Context.AppendTag(tag);
+ Context?.AppendTag(tag);
base.SetTags(operation);
}
@@ -168,12 +178,13 @@ protected override void SetTags(OpenApiOperation operation)
/// The generated tag name.
/// The number of segments to skip.
private void GenerateTagName(out string tagName, int skip = 1)
- {
+ {
+ if (Path is null) throw new InvalidOperationException("Path is null.");
var targetSegment = Path.Segments.Reverse().Skip(skip).FirstOrDefault();
switch (targetSegment)
{
- case ODataNavigationPropertySegment:
+ case ODataNavigationPropertySegment when Context is not null:
tagName = EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context);
break;
case ODataOperationImportSegment:
@@ -183,7 +194,7 @@ private void GenerateTagName(out string tagName, int skip = 1)
GenerateTagName(out tagName, skip);
break;
default:
- tagName = NavigationSource.Name + "." + NavigationSource.EntityType.Name;
+ tagName = NavigationSource?.Name + "." + NavigationSource?.EntityType.Name;
if (EdmOperation.IsAction())
{
tagName += ".Actions";
@@ -201,9 +212,8 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- if (EdmOperation.IsFunction())
+ if (EdmOperation.IsFunction() && EdmOperation is IEdmFunction function)
{
- IEdmFunction function = (IEdmFunction)EdmOperation;
AppendSystemQueryOptions(function, operation);
}
}
@@ -211,7 +221,8 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.Responses = Context.CreateResponses(EdmOperation, _document);
+ if (EdmOperation is not null && Context is not null)
+ operation.Responses = Context.CreateResponses(EdmOperation, _document);
base.SetResponses(operation);
}
@@ -223,7 +234,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_operationRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_operationRestriction.Permissions, _document).ToList();
}
///
@@ -247,8 +258,9 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
private void AppendSystemQueryOptions(IEdmFunction function, OpenApiOperation operation)
{
- if (function.ReturnType.IsCollection())
+ if (function.ReturnType.IsCollection() && Context is not null)
{
+ operation.Parameters ??= [];
// $top
if (Context.CreateTop(function, _document) is {} topParameter)
{
@@ -305,10 +317,10 @@ private void AppendSystemQueryOptions(IEdmFunction function, OpenApiOperation op
///
protected override void SetCustomLinkRelType()
{
- if (Context.Settings.CustomHttpMethodLinkRelMapping != null && EdmOperation != null)
+ if (Context is {Settings.CustomHttpMethodLinkRelMapping: not null} && EdmOperation != null)
{
LinkRelKey key = EdmOperation.IsAction() ? LinkRelKey.Action : LinkRelKey.Function;
- Context.Settings.CustomHttpMethodLinkRelMapping.TryGetValue(key, out string linkRelValue);
+ Context.Settings.CustomHttpMethodLinkRelMapping.TryGetValue(key, out var linkRelValue);
CustomLinkRel = linkRelValue;
}
}
@@ -316,10 +328,14 @@ protected override void SetCustomLinkRelType()
///
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs)
+ if (Context is { Settings.ShowExternalDocs: true })
{
- var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(EdmOperation, CustomLinkRel);
+ var externalDocs = (string.IsNullOrEmpty(TargetPath), string.IsNullOrEmpty(CustomLinkRel)) switch
+ {
+ (false, false) => Context.Model.GetLinkRecord(TargetPath!, CustomLinkRel!),
+ (true, false) when EdmOperation is not null => Context.Model.GetLinkRecord(EdmOperation, CustomLinkRel!),
+ (_, _) => null,
+ };
if (externalDocs != null)
{
@@ -335,14 +351,15 @@ protected override void SetExternalDocs(OpenApiOperation operation)
//
protected override void SetExtensions(OpenApiOperation operation)
{
- if (Context.Settings.EnablePagination && EdmOperation.ReturnType?.TypeKind() == EdmTypeKind.Collection)
+ if (Context is { Settings.EnablePagination: true } && EdmOperation?.ReturnType?.TypeKind() == EdmTypeKind.Collection)
{
- JsonObject extension = new JsonObject
+ var extension = new JsonObject
{
{ "nextLinkName", "@odata.nextLink"},
{ "operationName", Context.Settings.PageableOperationName}
};
-
+
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
base.SetExtensions(operation);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
index 8b2091f05..16f8f7f3b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
@@ -32,27 +32,29 @@ public EntityDeleteOperationHandler(OpenApiDocument document) : base(document)
///
public override HttpMethod OperationType => HttpMethod.Delete;
- private DeleteRestrictionsType _deleteRestrictions;
+ private DeleteRestrictionsType? _deleteRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _deleteRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
- var entityDeleteRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.DeleteRestrictions);
- _deleteRestrictions?.MergePropertiesIfNull(entityDeleteRestrictions);
- _deleteRestrictions ??= entityDeleteRestrictions;
+ if (Context is null) return;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _deleteRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
+ if (EntitySet is not null)
+ {
+ var entityDeleteRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.DeleteRestrictions);
+ _deleteRestrictions?.MergePropertiesIfNull(entityDeleteRestrictions);
+ _deleteRestrictions ??= entityDeleteRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
- IEdmEntityType entityType = EntitySet.EntityType;
- ODataKeySegment keySegment = Path.LastSegment as ODataKeySegment;
-
// Description
- string placeHolder = $"Delete entity from {EntitySet.Name}";
- if (keySegment.IsAlternateKey)
+ string placeHolder = $"Delete entity from {EntitySet?.Name}";
+ if (Path is {LastSegment: ODataKeySegment {IsAlternateKey: true} keySegment})
{
placeHolder = $"{placeHolder} by {keySegment.Identifier}";
}
@@ -60,13 +62,13 @@ protected override void SetBasicInfo(OpenApiOperation operation)
operation.Description = _deleteRestrictions?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is { Settings.EnableOperationId: true} && EntitySet?.EntityType is IEdmEntityType entityType)
{
string typeName = entityType.Name;
string operationName =$"Delete{Utils.UpperFirstChar(typeName)}";
- if (keySegment.IsAlternateKey)
+ if (Path is {LastSegment: ODataKeySegment {IsAlternateKey: true} keySegment2})
{
- string alternateKeyName = string.Join("", keySegment.Identifier.Split(',').Select(static x => Utils.UpperFirstChar(x)));
+ string alternateKeyName = string.Join("", keySegment2.Identifier.Split(',').Select(static x => Utils.UpperFirstChar(x)));
operationName = $"{operationName}By{alternateKeyName}";
}
operation.OperationId = $"{EntitySet.Name}.{typeName}.{operationName}";
@@ -78,6 +80,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ operation.Parameters ??= [];
operation.Parameters.Add(new OpenApiParameter
{
Name = "If-Match",
@@ -94,7 +97,7 @@ protected override void SetParameters(OpenApiOperation operation)
protected override void SetResponses(OpenApiOperation operation)
{
// Response for Delete methods should be 204 No Content
- OpenApiConvertSettings settings = Context.Settings.Clone();
+ OpenApiConvertSettings settings = Context?.Settings.Clone() ?? new();
settings.UseSuccessStatusCodeRange = false;
operation.AddErrorResponses(settings, _document, true);
@@ -108,7 +111,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_deleteRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_deleteRestrictions.Permissions, _document).ToList() ?? [];
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs
index 224c38333..b02d38abf 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs
@@ -35,39 +35,43 @@ public EntityGetOperationHandler(OpenApiDocument document) : base(document)
///
public override HttpMethod OperationType => HttpMethod.Get;
- private ReadRestrictionsType _readRestrictions;
+ private ReadRestrictionsType? _readRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- var entityReadRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions);
- _readRestrictions?.MergePropertiesIfNull(entityReadRestrictions);
- _readRestrictions ??= entityReadRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _readRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (Context is not null && EntitySet is not null)
+ {
+ var entityReadRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions);
+ _readRestrictions?.MergePropertiesIfNull(entityReadRestrictions);
+ _readRestrictions ??= entityReadRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
- IEdmEntityType entityType = EntitySet.EntityType;
- ODataKeySegment keySegment = Path.LastSegment as ODataKeySegment;
+ var keySegment = Path?.LastSegment as ODataKeySegment;
// Description
- string placeHolder = "Get entity from " + EntitySet.Name + " by key";
- if (keySegment.IsAlternateKey)
+ string placeHolder = "Get entity from " + EntitySet?.Name + " by key";
+ if (keySegment?.IsAlternateKey ?? false)
{
placeHolder = $"{placeHolder} ({keySegment.Identifier})";
}
operation.Summary = _readRestrictions?.ReadByKeyRestrictions?.Description ?? placeHolder;
- operation.Description = _readRestrictions?.ReadByKeyRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(entityType);
+ operation.Description = _readRestrictions?.ReadByKeyRestrictions?.LongDescription ??
+ (EntitySet is null ? null : Context?.Model.GetDescriptionAnnotation(EntitySet.EntityType));
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && EntitySet?.EntityType.Name is string entityTypeName)
{
- string typeName = entityType.Name;
+ string typeName = entityTypeName;
string operationName = $"Get{Utils.UpperFirstChar(typeName)}";
- if (keySegment.IsAlternateKey)
+ if (keySegment?.IsAlternateKey ?? false)
{
string alternateKeyName = string.Join("", keySegment.Identifier.Split(',').Select(static x => Utils.UpperFirstChar(x)));
operationName = $"{operationName}By{alternateKeyName}";
@@ -81,47 +85,49 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ if (Context is null || EntitySet is null) return;
+
// $select
- OpenApiParameter parameter = Context.CreateSelect(EntitySet);
- if (parameter != null)
+ if (Context.CreateSelect(EntitySet) is {} sParameter)
{
- operation.Parameters.Add(parameter);
+ operation.Parameters ??= [];
+ operation.Parameters.Add(sParameter);
}
// $expand
- parameter = Context.CreateExpand(EntitySet);
- if (parameter != null)
+ if (Context.CreateExpand(EntitySet) is {} eParameter)
{
- operation.Parameters.Add(parameter);
+ operation.Parameters ??= [];
+ operation.Parameters.Add(eParameter);
}
}
///
protected override void SetResponses(OpenApiOperation operation)
{
- IOpenApiSchema schema = null;
- IDictionary links = null;
+ IOpenApiSchema? schema = null;
+ IDictionary? links = null;
- if (Context.Settings.EnableDerivedTypesReferencesForResponses)
+ if (EntitySet is not null)
{
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model, _document);
- }
+ if (Context is {Settings.EnableDerivedTypesReferencesForResponses: true})
+ {
+ schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model, _document);
+ }
- if (Context.Settings.ShowLinks)
- {
- links = Context.CreateLinks(entityType: EntitySet.EntityType, entityName: EntitySet.Name,
- entityKind: EntitySet.ContainerElementKind.ToString(), path: Path, parameters: PathParameters);
- }
+ if (Context is {Settings.ShowLinks: true} && Path is not null)
+ {
+ links = Context.CreateLinks(entityType: EntitySet.EntityType, entityName: EntitySet.Name,
+ entityKind: EntitySet.ContainerElementKind.ToString(), path: Path, parameters: PathParameters);
+ }
- if (schema == null)
- {
- schema = new OpenApiSchemaReference(EntitySet.EntityType.FullName(), _document);
+ schema ??= new OpenApiSchemaReference(EntitySet.EntityType.FullName(), _document);
}
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponse
{
Description = "Retrieved entity",
@@ -139,7 +145,8 @@ protected override void SetResponses(OpenApiOperation operation)
}
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -157,12 +164,12 @@ protected override void SetSecurity(OpenApiOperation operation)
readBase = _readRestrictions.ReadByKeyRestrictions;
}
- if (readBase == null && readBase.Permissions == null)
+ if (readBase == null || readBase.Permissions == null)
{
return;
}
- operation.Security = Context.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs
index 9dba9d979..e4b36f8ef 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs
@@ -3,11 +3,14 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
@@ -36,28 +39,32 @@ public EntitySetGetOperationHandler(OpenApiDocument document) : base(document)
///
public override HttpMethod OperationType => HttpMethod.Get;
- private ReadRestrictionsType _readRestrictions;
+ private ReadRestrictionsType? _readRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- var entityReadRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions);
- _readRestrictions?.MergePropertiesIfNull(entityReadRestrictions);
- _readRestrictions ??= entityReadRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _readRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (Context is not null && EntitySet is not null)
+ {
+ var entityReadRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions);
+ _readRestrictions?.MergePropertiesIfNull(entityReadRestrictions);
+ _readRestrictions ??= entityReadRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Descriptions
- string placeHolder = "Get entities from " + EntitySet.Name;
+ string placeHolder = "Get entities from " + EntitySet?.Name;
operation.Summary = _readRestrictions?.Description ?? placeHolder;
- operation.Description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(EntitySet);
+ operation.Description = _readRestrictions?.LongDescription ?? Context?.Model.GetDescriptionAnnotation(EntitySet);
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && EntitySet is not null)
{
string typeName = EntitySet.EntityType.Name;
operation.OperationId = EntitySet.Name + "." + typeName + ".List" + Utils.UpperFirstChar(typeName);
@@ -66,13 +73,14 @@ protected override void SetBasicInfo(OpenApiOperation operation)
protected override void SetExtensions(OpenApiOperation operation)
{
- if (Context.Settings.EnablePagination)
+ if (Context is {Settings.EnablePagination: true})
{
- JsonObject extension = new JsonObject
+ var extension = new JsonObject
{
{ "nextLinkName", "@odata.nextLink"},
{ "operationName", Context.Settings.PageableOperationName}
};
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
base.SetExtensions(operation);
@@ -83,41 +91,43 @@ protected override void SetExtensions(OpenApiOperation operation)
protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ if (Context is null || EntitySet is null) return;
// The parameters array contains Parameter Objects for all system query options allowed for this collection,
// and it does not list system query options not allowed for this collection, see terms
// Capabilities.TopSupported, Capabilities.SkipSupported, Capabilities.SearchRestrictions,
// Capabilities.FilterRestrictions, and Capabilities.CountRestrictions
// $top
- var parameter = Context.CreateTop(TargetPath, _document) ?? Context.CreateTop(EntitySet, _document);
+ operation.Parameters ??= [];
+ var parameter = (TargetPath is null ? null : Context.CreateTop(TargetPath, _document)) ?? Context.CreateTop(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $skip
- parameter = Context.CreateSkip(TargetPath, _document) ?? Context.CreateSkip(EntitySet, _document);
+ parameter = (TargetPath is null ? null : Context.CreateSkip(TargetPath, _document)) ?? Context.CreateSkip(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $search
- parameter = Context.CreateSearch(TargetPath, _document) ?? Context.CreateSearch(EntitySet, _document);
+ parameter = (TargetPath is null ? null : Context.CreateSearch(TargetPath, _document)) ?? Context.CreateSearch(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $filter
- parameter = Context.CreateFilter(TargetPath, _document) ?? Context.CreateFilter(EntitySet, _document);
+ parameter = (TargetPath is null ? null : Context.CreateFilter(TargetPath, _document)) ?? Context.CreateFilter(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $count
- parameter = Context.CreateCount(TargetPath, _document) ?? Context.CreateCount(EntitySet, _document);
+ parameter = (TargetPath is null ? null : Context.CreateCount(TargetPath, _document)) ?? Context.CreateCount(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -128,21 +138,21 @@ protected override void SetParameters(OpenApiOperation operation)
// of just providing a comma-separated list of properties can be expressed via an array-valued
// parameter with an enum constraint
// $order
- parameter = Context.CreateOrderBy(TargetPath, EntitySet.EntityType) ?? Context.CreateOrderBy(EntitySet);
+ parameter = (TargetPath is null ? null : Context.CreateOrderBy(TargetPath, EntitySet.EntityType)) ?? Context.CreateOrderBy(EntitySet);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $select
- parameter = Context.CreateSelect(TargetPath, EntitySet.EntityType) ?? Context.CreateSelect(EntitySet);
+ parameter = (TargetPath is null ? null : Context.CreateSelect(TargetPath, EntitySet.EntityType)) ?? Context.CreateSelect(EntitySet);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $expand
- parameter = Context.CreateExpand(TargetPath, EntitySet.EntityType) ?? Context.CreateExpand(EntitySet);
+ parameter = (TargetPath is null ? null : Context.CreateExpand(TargetPath, EntitySet.EntityType)) ?? Context.CreateExpand(EntitySet);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -155,12 +165,13 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
- new OpenApiResponseReference($"{EntitySet.EntityType.FullName()}{Constants.CollectionSchemaSuffix}", _document)
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ new OpenApiResponseReference($"{EntitySet?.EntityType.FullName()}{Constants.CollectionSchemaSuffix}", _document)
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -172,7 +183,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs
index 4719ddee7..e3a79902c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs
@@ -5,6 +5,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
@@ -30,7 +31,7 @@ protected EntitySetOperationHandler(OpenApiDocument document) : base(document)
///
/// Gets/sets the .
///
- protected IEdmEntitySet EntitySet { get; private set; }
+ protected IEdmEntitySet? EntitySet { get; private set; }
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -38,19 +39,18 @@ protected override void Initialize(ODataContext context, ODataPath path)
base.Initialize(context, path);
// get the entity set.
- ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
-
- EntitySet = navigationSourceSegment.NavigationSource as IEdmEntitySet;
+ if (path.FirstSegment is ODataNavigationSourceSegment {NavigationSource: IEdmEntitySet navigationSource})
+ EntitySet = navigationSource;
}
///
protected override void SetTags(OpenApiOperation operation)
{
- var tagName = EntitySet.Name + "." + EntitySet.EntityType.Name;
+ var tagName = EntitySet?.Name + "." + EntitySet?.EntityType.Name;
operation.Tags ??= new HashSet();
operation.Tags.Add(new OpenApiTagReference(tagName, _document));
- Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ Context?.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
{
Name = tagName
});
@@ -61,6 +61,7 @@ protected override void SetTags(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("operation"));
base.SetExtensions(operation);
@@ -69,10 +70,10 @@ protected override void SetExtensions(OpenApiOperation operation)
///
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs)
+ if (Context is {Settings.ShowExternalDocs: true} && CustomLinkRel is not null)
{
- var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(EntitySet, CustomLinkRel);
+ var externalDocs = (string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetLinkRecord(TargetPath, CustomLinkRel)) ??
+ (EntitySet is null ? null : Context.Model.GetLinkRecord(EntitySet, CustomLinkRel));
if (externalDocs != null)
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs
index 046ba8380..235b8fd2e 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs
@@ -36,28 +36,32 @@ public EntitySetPostOperationHandler(OpenApiDocument document) : base(document)
///
public override HttpMethod OperationType => HttpMethod.Post;
- private InsertRestrictionsType _insertRestrictions;
+ private InsertRestrictionsType? _insertRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _insertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
- var entityInsertRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.InsertRestrictions);
- _insertRestrictions?.MergePropertiesIfNull(entityInsertRestrictions);
- _insertRestrictions ??= entityInsertRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _insertRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
+ if (Context is not null && EntitySet is not null)
+ {
+ var entityInsertRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.InsertRestrictions);
+ _insertRestrictions?.MergePropertiesIfNull(entityInsertRestrictions);
+ _insertRestrictions ??= entityInsertRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Add new entity to " + EntitySet.Name;
+ string placeHolder = "Add new entity to " + EntitySet?.Name;
operation.Summary = _insertRestrictions?.Description ?? placeHolder;
operation.Description = _insertRestrictions?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && EntitySet is not null)
{
string typeName = EntitySet.EntityType.Name;
operation.OperationId = EntitySet.Name + "." + typeName + ".Create" + Utils.UpperFirstChar(typeName);
@@ -85,7 +89,7 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode201,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode201,
new OpenApiResponse
{
Description = "Created entity",
@@ -94,7 +98,8 @@ protected override void SetResponses(OpenApiOperation operation)
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -106,7 +111,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_insertRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -136,16 +141,14 @@ private IDictionary GetContentDescription()
var schema = GetEntitySchema();
var content = new Dictionary();
- if (EntitySet.EntityType.HasStream)
+ if (EntitySet is {EntityType.HasStream: true})
{
- IEnumerable mediaTypes = Context.Model.GetCollection(EntitySet.EntityType,
- CoreConstants.AcceptableMediaTypes);
-
- if (mediaTypes != null)
+ if (Context?.Model.GetCollection(EntitySet.EntityType,
+ CoreConstants.AcceptableMediaTypes) is {} mediaTypes)
{
foreach (string item in mediaTypes)
{
- content.Add(item, null);
+ content.Add(item, new());
}
}
else
@@ -164,8 +167,7 @@ private IDictionary GetContentDescription()
else
{
// Add the annotated request content media types
- IEnumerable mediaTypes = _insertRestrictions?.RequestContentTypes;
- if (mediaTypes != null)
+ if (_insertRestrictions?.RequestContentTypes is {} mediaTypes)
{
foreach (string mediaType in mediaTypes)
{
@@ -192,9 +194,10 @@ private IDictionary GetContentDescription()
/// Get the entity schema.
///
/// The entity schema.
- private IOpenApiSchema GetEntitySchema()
+ private IOpenApiSchema? GetEntitySchema()
{
- return Context.Settings.EnableDerivedTypesReferencesForRequestBody ?
+ if (EntitySet is null) return null;
+ return Context?.Settings.EnableDerivedTypesReferencesForRequestBody ?? false ?
EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model, _document) :
new OpenApiSchemaReference(EntitySet.EntityType.FullName(), _document);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs
index a34d6d9f2..81be9e2bd 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs
@@ -30,27 +30,30 @@ protected EntityUpdateOperationHandler(OpenApiDocument document):base(document)
{
}
- private UpdateRestrictionsType _updateRestrictions;
+ private UpdateRestrictionsType? _updateRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
- var entityUpdateRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions);
- _updateRestrictions?.MergePropertiesIfNull(entityUpdateRestrictions);
- _updateRestrictions ??= entityUpdateRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _updateRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+ if (Context is not null && EntitySet is not null)
+ {
+ var entityUpdateRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions);
+ _updateRestrictions?.MergePropertiesIfNull(entityUpdateRestrictions);
+ _updateRestrictions ??= entityUpdateRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
- IEdmEntityType entityType = EntitySet.EntityType;
- ODataKeySegment keySegment = Path.LastSegment as ODataKeySegment;
+ var keySegment = Path?.LastSegment as ODataKeySegment;
// Summary and Description
- string placeHolder = "Update entity in " + EntitySet.Name;
- if (keySegment.IsAlternateKey)
+ string placeHolder = "Update entity in " + EntitySet?.Name;
+ if (keySegment is {IsAlternateKey: true})
{
placeHolder = $"{placeHolder} by {keySegment.Identifier}";
}
@@ -58,12 +61,12 @@ protected override void SetBasicInfo(OpenApiOperation operation)
operation.Description = _updateRestrictions?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && EntitySet?.EntityType is {} entityType)
{
string typeName = entityType.Name;
string prefix = OperationType == HttpMethod.Patch ? "Update" : "Set";
string operationName = $"{prefix}{ Utils.UpperFirstChar(typeName)}";
- if (keySegment.IsAlternateKey)
+ if (keySegment is {IsAlternateKey: true})
{
string alternateKeyName = string.Join("", keySegment.Identifier.Split(',').Select(static x => Utils.UpperFirstChar(x)));
operationName = $"{operationName}By{alternateKeyName}";
@@ -89,10 +92,9 @@ protected IDictionary GetContent()
{
var schema = GetOpenApiSchema();
var content = new Dictionary();
- IEnumerable mediaTypes = _updateRestrictions?.RequestContentTypes;
// Add the annotated request content media types
- if (mediaTypes != null)
+ if (_updateRestrictions?.RequestContentTypes is {} mediaTypes)
{
foreach (string mediaType in mediaTypes)
{
@@ -109,7 +111,7 @@ protected IDictionary GetContent()
{
Schema = schema
});
- };
+ }
return content;
}
@@ -117,7 +119,8 @@ protected IDictionary GetContent()
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
+ if (GetOpenApiSchema() is {} schema)
+ operation.AddErrorResponses(Context?.Settings ?? new(), _document, true, schema);
base.SetResponses(operation);
}
@@ -128,7 +131,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -149,11 +152,13 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
}
}
- private IOpenApiSchema GetOpenApiSchema()
+ private IOpenApiSchema? GetOpenApiSchema()
{
- if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
+ if (EntitySet is null) return null;
+ if (Context is {Settings.EnableDerivedTypesReferencesForRequestBody: true} &&
+ EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model, _document) is {} schema)
{
- return EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model, _document);
+ return schema;
}
return new OpenApiSchemaReference(EntitySet.EntityType.FullName(), _document);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs
index be07c065f..4d812c1c7 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs
@@ -21,6 +21,6 @@ internal interface IOperationHandlerProvider
/// The operation type.
/// The Open API document to use to lookup references.
/// The corresponding .
- IOperationHandler GetHandler(ODataPathKind pathKind, HttpMethod operationType, OpenApiDocument document);
+ IOperationHandler? GetHandler(ODataPathKind pathKind, HttpMethod operationType, OpenApiDocument document);
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
index af94ff02c..bacd851e2 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
@@ -22,7 +22,7 @@ public MediaEntityDeleteOperationHandler(OpenApiDocument document) : base(docume
///
public override HttpMethod OperationType => HttpMethod.Delete;
- private DeleteRestrictionsType _deleteRestrictions;
+ private DeleteRestrictionsType? _deleteRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
@@ -30,17 +30,18 @@ protected override void Initialize(ODataContext context, ODataPath path)
if (Property != null)
{
- _deleteRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
+ if (!string.IsNullOrEmpty(TargetPath))
+ _deleteRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
if (Property is IEdmNavigationProperty)
{
- var navigationDeleteRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
+ var navigationDeleteRestrictions = Context?.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
.RestrictedProperties?.FirstOrDefault()?.DeleteRestrictions;
_deleteRestrictions?.MergePropertiesIfNull(navigationDeleteRestrictions);
_deleteRestrictions ??= navigationDeleteRestrictions;
}
else
{
- var propertyDeleteRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.DeleteRestrictions);
+ var propertyDeleteRestrictions = Context?.Model.GetRecord(Property, CapabilitiesConstants.DeleteRestrictions);
_deleteRestrictions?.MergePropertiesIfNull(propertyDeleteRestrictions);
_deleteRestrictions ??= propertyDeleteRestrictions;
}
@@ -51,19 +52,19 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary
- string placeholderValue = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "media content";
+ string placeholderValue = LastSegmentIsStreamPropertySegment && Path is {LastSegment.Identifier: not null} ? Path.LastSegment.Identifier : "media content";
operation.Summary = _deleteRestrictions?.Description;
operation.Summary ??= IsNavigationPropertyPath
- ? $"Delete {placeholderValue} for the navigation property {NavigationProperty.Name} in {NavigationSourceSegment.NavigationSource.Name}"
- : $"Delete {placeholderValue} for {NavigationSourceSegment.EntityType.Name} in {NavigationSourceSegment.Identifier}";
+ ? $"Delete {placeholderValue} for the navigation property {NavigationProperty?.Name} in {NavigationSourceSegment?.NavigationSource.Name}"
+ : $"Delete {placeholderValue} for {NavigationSourceSegment?.EntityType.Name} in {NavigationSourceSegment?.Identifier}";
// Description
- operation.Description = _deleteRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Property);
+ operation.Description = _deleteRestrictions?.LongDescription ?? Context?.Model.GetDescriptionAnnotation(Property);
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
- string identifier = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "Content";
+ string identifier = LastSegmentIsStreamPropertySegment && Path is {LastSegment.Identifier: not null} ? Path.LastSegment.Identifier : "Content";
operation.OperationId = GetOperationId("Delete", identifier);
}
@@ -75,6 +76,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ operation.Parameters ??= [];
operation.Parameters.Add(new OpenApiParameter
{
Name = "If-Match",
@@ -91,7 +93,7 @@ protected override void SetParameters(OpenApiOperation operation)
protected override void SetResponses(OpenApiOperation operation)
{
// Response for Delete methods should be 204 No Content
- OpenApiConvertSettings settings = Context.Settings.Clone();
+ OpenApiConvertSettings settings = Context?.Settings.Clone() ?? new();
settings.UseSuccessStatusCodeRange = false;
operation.AddErrorResponses(settings, _document, true);
@@ -105,7 +107,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_deleteRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_deleteRestrictions.Permissions, _document).ToList() ?? [];
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
index 1f6a695b7..e44471ed4 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
@@ -30,7 +30,7 @@ public MediaEntityGetOperationHandler(OpenApiDocument document) : base(document)
}
///
public override HttpMethod OperationType => HttpMethod.Get;
- private ReadRestrictionsType _readRestrictions = null;
+ private ReadRestrictionsType? _readRestrictions = null;
protected override void Initialize(ODataContext context, ODataPath path)
{
@@ -38,17 +38,18 @@ protected override void Initialize(ODataContext context, ODataPath path)
if (Property != null)
{
- _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (!string.IsNullOrEmpty(TargetPath))
+ _readRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
if (Property is IEdmNavigationProperty)
{
- var navigationReadRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
+ var navigationReadRestrictions = Context?.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
.RestrictedProperties?.FirstOrDefault()?.ReadRestrictions;
_readRestrictions?.MergePropertiesIfNull(navigationReadRestrictions);
_readRestrictions ??= navigationReadRestrictions;
}
else
{
- var propertyReadRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.ReadRestrictions);
+ var propertyReadRestrictions = Context?.Model.GetRecord(Property, CapabilitiesConstants.ReadRestrictions);
_readRestrictions?.MergePropertiesIfNull(propertyReadRestrictions);
_readRestrictions ??= propertyReadRestrictions;
}
@@ -59,34 +60,35 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary
- string placeholderValue = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "media content";
+ var placeholderValue = LastSegmentIsStreamPropertySegment ? Path?.LastSegment?.Identifier : "media content";
operation.Summary = _readRestrictions?.Description;
operation.Summary ??= IsNavigationPropertyPath
- ? $"Get {placeholderValue} for the navigation property {NavigationProperty.Name} from {NavigationSourceSegment.NavigationSource.Name}"
- : $"Get {placeholderValue} for {NavigationSourceSegment.EntityType.Name} from {NavigationSourceSegment.Identifier}";
+ ? $"Get {placeholderValue} for the navigation property {NavigationProperty?.Name} from {NavigationSourceSegment?.NavigationSource.Name}"
+ : $"Get {placeholderValue} for {NavigationSourceSegment?.EntityType.Name} from {NavigationSourceSegment?.Identifier}";
// Description
- string description;
+ string? description;
if (Property is IEdmNavigationProperty)
{
description = LastSegmentIsKeySegment
? _readRestrictions?.ReadByKeyRestrictions?.LongDescription
: _readRestrictions?.LongDescription
- ?? Context.Model.GetDescriptionAnnotation(Property);
+ ?? Context?.Model.GetDescriptionAnnotation(Property);
}
else
{
// Structural property
- description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Property);
+ description = _readRestrictions?.LongDescription ?? Context?.Model.GetDescriptionAnnotation(Property);
}
- operation.Description = description;
+ if (!string.IsNullOrEmpty(description))
+ operation.Description = description;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} &&
+ (LastSegmentIsStreamPropertySegment ? Path?.LastSegment?.Identifier : "Content") is string identifier)
{
- string identifier = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "Content";
operation.OperationId = GetOperationId("Get", identifier);
}
}
@@ -97,7 +99,7 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponse
{
Description = "Retrieved media content",
@@ -105,7 +107,8 @@ protected override void SetResponses(OpenApiOperation operation)
}
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -113,9 +116,8 @@ protected override void SetResponses(OpenApiOperation operation)
///
protected override void SetSecurity(OpenApiOperation operation)
{
- IEdmVocabularyAnnotatable annotatableNavigationSource = (IEdmVocabularyAnnotatable)NavigationSourceSegment.NavigationSource;
- ReadRestrictionsType read = Context.Model.GetRecord(annotatableNavigationSource, CapabilitiesConstants.ReadRestrictions);
- if (read == null)
+ if (NavigationSourceSegment?.NavigationSource is not IEdmVocabularyAnnotatable annotatableNavigationSource ||
+ Context?.Model.GetRecord(annotatableNavigationSource, CapabilitiesConstants.ReadRestrictions) is not {} read)
{
return;
}
@@ -126,7 +128,7 @@ protected override void SetSecurity(OpenApiOperation operation)
readBase = read.ReadByKeyRestrictions;
}
- if (readBase == null && readBase.Permissions == null)
+ if (readBase == null || readBase.Permissions == null)
{
return;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs
index 488046d6c..cc954648c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs
@@ -10,6 +10,7 @@
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Core;
+using System;
using System.Collections.Generic;
using System.Linq;
@@ -31,7 +32,7 @@ protected MediaEntityOperationalHandler(OpenApiDocument document) : base(documen
///
/// Gets/Sets the NavigationSource segment
///
- protected ODataNavigationSourceSegment NavigationSourceSegment { get; private set; }
+ protected ODataNavigationSourceSegment? NavigationSourceSegment { get; private set; }
///
/// Gets/Sets flag indicating whether path is navigation property path
@@ -50,12 +51,12 @@ protected MediaEntityOperationalHandler(OpenApiDocument document) : base(documen
///
/// Gets the media entity property.
///
- protected IEdmProperty Property { get; private set; }
+ protected IEdmProperty? Property { get; private set; }
///
/// Gets the navigation property.
///
- protected IEdmNavigationProperty NavigationProperty { get; private set; }
+ protected IEdmNavigationProperty? NavigationProperty { get; private set; }
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -64,12 +65,13 @@ protected override void Initialize(ODataContext context, ODataPath path)
NavigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
// Check whether path is a navigation property path
- IsNavigationPropertyPath = Path.Segments.Contains(
- Path.Segments.FirstOrDefault(segment => segment is ODataNavigationPropertySegment));
+ IsNavigationPropertyPath = Path is not null &&
+ Path.Segments.OfType().FirstOrDefault() is {} firstPropSegment &&
+ Path.Segments.Contains(firstPropSegment);
- LastSegmentIsStreamPropertySegment = Path.LastSegment.Kind == ODataSegmentKind.StreamProperty;
+ LastSegmentIsStreamPropertySegment = Path?.LastSegment?.Kind == ODataSegmentKind.StreamProperty;
- LastSegmentIsStreamContentSegment = Path.LastSegment.Kind == ODataSegmentKind.StreamContent;
+ LastSegmentIsStreamContentSegment = Path?.LastSegment?.Kind == ODataSegmentKind.StreamContent;
LastSegmentIsKeySegment = path.LastSegment is ODataKeySegment;
@@ -87,12 +89,12 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetTags(OpenApiOperation operation)
{
- string tagIdentifier = IsNavigationPropertyPath
+ string tagIdentifier = IsNavigationPropertyPath && Path is not null && Context is not null
? EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context)
- : NavigationSourceSegment.Identifier + "." + NavigationSourceSegment.EntityType.Name;
+ : NavigationSourceSegment?.Identifier + "." + NavigationSourceSegment?.EntityType.Name;
- Context.AddExtensionToTag(tagIdentifier, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ Context?.AddExtensionToTag(tagIdentifier, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
{
Name = tagIdentifier
});
@@ -118,17 +120,19 @@ protected string GetOperationId(string prefix, string identifier)
Utils.CheckArgumentNullOrEmpty(prefix, nameof(prefix));
Utils.CheckArgumentNullOrEmpty(identifier, nameof(identifier));
- var items = new List
+ var items = NavigationSourceSegment is null ? [] : new List
{
NavigationSourceSegment.Identifier
};
+ if (Path is null) throw new InvalidOperationException("Path is null.");
+
ODataSegment lastSegment = Path.Segments.Last(c => c is ODataStreamContentSegment || c is ODataStreamPropertySegment);
foreach (ODataSegment segment in Path.Segments.Skip(1))
{
if (segment == lastSegment)
{
- if (!IsNavigationPropertyPath)
+ if (!IsNavigationPropertyPath && NavigationSourceSegment is not null)
{
string typeName = NavigationSourceSegment.EntityType.Name;
items.Add(typeName);
@@ -138,8 +142,11 @@ protected string GetOperationId(string prefix, string identifier)
{
// Remove the last navigation property segment for navigation property paths,
// as this will be included within the prefixed name of the operation id
- items.Remove(NavigationProperty.Name);
- items.Add(prefix + Utils.UpperFirstChar(NavigationProperty.Name) + Utils.UpperFirstChar(identifier));
+ if (NavigationProperty is not null)
+ {
+ items.Remove(NavigationProperty.Name);
+ items.Add(prefix + Utils.UpperFirstChar(NavigationProperty.Name) + Utils.UpperFirstChar(identifier));
+ }
}
break;
}
@@ -152,7 +159,7 @@ protected string GetOperationId(string prefix, string identifier)
}
}
- return $"{string.Join(".", items)}-{Path.GetPathHash(Context.Settings)}";
+ return $"{string.Join(".", items)}-{Path.GetPathHash(Context?.Settings ?? new())}";
}
///
@@ -163,12 +170,6 @@ protected IDictionary GetContentDescription()
{
// Fetch the respective AcceptableMediaTypes
(_, var property) = GetStreamElements();
- IEnumerable mediaTypes = null;
- if (property != null)
- {
- mediaTypes = Context.Model.GetCollection(property,
- CoreConstants.AcceptableMediaTypes);
- }
OpenApiSchema schema = new()
{
@@ -177,7 +178,9 @@ protected IDictionary GetContentDescription()
};
var content = new Dictionary();
- if (mediaTypes != null)
+ if (property is not null &&
+ Context?.Model.GetCollection(property,
+ CoreConstants.AcceptableMediaTypes) is {} mediaTypes)
{
foreach (string item in mediaTypes)
{
@@ -203,35 +206,44 @@ protected IDictionary GetContentDescription()
/// Gets the stream property and entity type declaring the stream property.
///
/// The stream property and entity type declaring the stream property.
- protected (IEdmEntityType entityType, IEdmProperty property) GetStreamElements()
+ protected (IEdmEntityType? entityType, IEdmProperty? property) GetStreamElements()
{
// Only ODataStreamPropertySegment is annotatable
- if (!LastSegmentIsStreamPropertySegment && !LastSegmentIsStreamContentSegment) return (null, null);
+ if (!LastSegmentIsStreamPropertySegment && !LastSegmentIsStreamContentSegment || Path is null) return (null, null);
// Retrieve the entity type of the segment before the stream property segment
var entityType = LastSegmentIsStreamContentSegment
- ? Path.Segments.ElementAtOrDefault(Path.Segments.Count - 3).EntityType
- : Path.Segments.ElementAtOrDefault(Path.Segments.Count - 2).EntityType;
+ ? Path.Segments.ElementAtOrDefault(Path.Segments.Count - 3)?.EntityType
+ : Path.Segments.ElementAtOrDefault(Path.Segments.Count - 2)?.EntityType;
+
+ if (entityType is null) return (null, null);
// The stream property can either be a structural type or a navigation property type
- ODataSegment lastSegmentProp = LastSegmentIsStreamContentSegment
+ var lastSegmentProp = LastSegmentIsStreamContentSegment
? Path.Segments.Reverse().Skip(1).FirstOrDefault()
- : Path.Segments.LastOrDefault(c => c is ODataStreamPropertySegment);
- IEdmProperty property = GetStructuralProperty(entityType, lastSegmentProp.Identifier);
- if (property == null)
+ : Path.Segments.OfType().LastOrDefault();
+
+ if (lastSegmentProp?.Identifier is not string lastIdentifier) return (null, null);
+
+ if (GetStructuralProperty(entityType, lastIdentifier) is IEdmProperty property)
{
- property = GetNavigationProperty(entityType, lastSegmentProp.Identifier);
+ return (entityType, property);
}
- return (entityType, property);
+ if (GetNavigationProperty(entityType, lastIdentifier) is IEdmProperty navigationProperty)
+ {
+ return (entityType, navigationProperty);
+ }
+
+ return (null, null);
}
- private IEdmStructuralProperty GetStructuralProperty(IEdmEntityType entityType, string identifier)
+ private static IEdmStructuralProperty? GetStructuralProperty(IEdmEntityType entityType, string identifier)
{
return entityType.StructuralProperties().FirstOrDefault(x => x.Name.Equals(identifier));
}
- private IEdmNavigationProperty GetNavigationProperty(IEdmEntityType entityType, string identifier)
+ private static IEdmNavigationProperty? GetNavigationProperty(IEdmEntityType entityType, string identifier)
{
return entityType.DeclaredNavigationProperties().FirstOrDefault(x => x.Name.Equals(identifier));
}
@@ -239,10 +251,14 @@ private IEdmNavigationProperty GetNavigationProperty(IEdmEntityType entityType,
///
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs && Property != null)
+ if (Context is { Settings.ShowExternalDocs: true } && Property != null)
{
- var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(Property, CustomLinkRel);
+ var externalDocs = (string.IsNullOrEmpty(TargetPath), string.IsNullOrEmpty(CustomLinkRel)) switch
+ {
+ (_, true) => null,
+ (false, false) => Context.Model.GetLinkRecord(TargetPath!, CustomLinkRel!),
+ (_, false) => Context.Model.GetLinkRecord(Property, CustomLinkRel!),
+ };
if (externalDocs != null)
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs
index 0fde994a4..66db24322 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs
@@ -33,7 +33,7 @@ public MediaEntityPutOperationHandler(OpenApiDocument document):base(document)
///
public override HttpMethod OperationType => HttpMethod.Put;
- private UpdateRestrictionsType _updateRestrictions = null;
+ private UpdateRestrictionsType? _updateRestrictions = null;
protected override void Initialize(ODataContext context, ODataPath path)
{
@@ -41,17 +41,18 @@ protected override void Initialize(ODataContext context, ODataPath path)
if (Property != null)
{
- _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+ if (!string.IsNullOrEmpty(TargetPath))
+ _updateRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
if (Property is IEdmNavigationProperty)
{
- var navigationUpdateRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
+ var navigationUpdateRestrictions = Context?.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
.RestrictedProperties?.FirstOrDefault()?.UpdateRestrictions;
_updateRestrictions?.MergePropertiesIfNull(navigationUpdateRestrictions);
_updateRestrictions ??= navigationUpdateRestrictions;
}
else
{
- var propertyUpdateRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.UpdateRestrictions);
+ var propertyUpdateRestrictions = Context?.Model.GetRecord(Property, CapabilitiesConstants.UpdateRestrictions);
_updateRestrictions?.MergePropertiesIfNull(propertyUpdateRestrictions);
_updateRestrictions ??= propertyUpdateRestrictions;
}
@@ -62,19 +63,19 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary
- string placeholderValue = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "media content";
+ var placeholderValue = LastSegmentIsStreamPropertySegment ? Path?.LastSegment?.Identifier : "media content";
operation.Summary = _updateRestrictions?.Description;
operation.Summary ??= IsNavigationPropertyPath
- ? $"Update {placeholderValue} for the navigation property {NavigationProperty.Name} in {NavigationSourceSegment.NavigationSource.Name}"
- : $"Update {placeholderValue} for {NavigationSourceSegment.EntityType.Name} in {NavigationSourceSegment.Identifier}";
+ ? $"Update {placeholderValue} for the navigation property {NavigationProperty?.Name} in {NavigationSourceSegment?.NavigationSource.Name}"
+ : $"Update {placeholderValue} for {NavigationSourceSegment?.EntityType.Name} in {NavigationSourceSegment?.Identifier}";
// Description
- operation.Description = _updateRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Property);
+ operation.Description = _updateRestrictions?.LongDescription ?? Context?.Model.GetDescriptionAnnotation(Property);
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
- string identifier = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "Content";
+ var identifier = LastSegmentIsStreamPropertySegment && Path?.LastSegment?.Identifier is string lastIdentifier ? lastIdentifier : "Content";
operation.OperationId = GetOperationId("Update", identifier);
}
}
@@ -95,18 +96,18 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- if (LastSegmentIsStreamPropertySegment && Path.LastSegment.Identifier.Equals(Constants.Content, StringComparison.OrdinalIgnoreCase))
+ if (LastSegmentIsStreamPropertySegment && Constants.Content.Equals(Path?.LastSegment?.Identifier, StringComparison.OrdinalIgnoreCase))
{
// Get the entity type declaring this stream property.
(var entityType, _) = GetStreamElements();
var schema = new OpenApiSchemaReference(entityType.FullName(), _document);
- operation.AddErrorResponses(Context.Settings, _document, addNoContent: true, schema: schema);
+ operation.AddErrorResponses(Context?.Settings ?? new(), _document, addNoContent: true, schema: schema);
}
else
{
- operation.AddErrorResponses(Context.Settings, _document, true);
+ operation.AddErrorResponses(Context?.Settings ?? new(), _document, true);
}
base.SetResponses(operation);
@@ -115,9 +116,9 @@ protected override void SetResponses(OpenApiOperation operation)
///
protected override void SetSecurity(OpenApiOperation operation)
{
- IEdmVocabularyAnnotatable annotatableNavigationSource = (IEdmVocabularyAnnotatable)NavigationSourceSegment.NavigationSource;
- UpdateRestrictionsType update = Context.Model.GetRecord(annotatableNavigationSource, CapabilitiesConstants.UpdateRestrictions);
- if (update == null || update.Permissions == null)
+ if (NavigationSourceSegment?.NavigationSource is not IEdmVocabularyAnnotatable annotatableNavigationSource ||
+ Context?.Model.GetRecord(annotatableNavigationSource, CapabilitiesConstants.UpdateRestrictions) is not {} update ||
+ update.Permissions == null)
{
return;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs
index 4ec24a1ee..f3114b698 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs
@@ -33,7 +33,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
operation.Summary = $"Get OData metadata (CSDL) document";
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
string routePrefix = Context.Settings.PathPrefix ?? "";
if (Context.Settings.PathPrefix != null)
@@ -60,7 +60,7 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponse
{
Description = "Retrieved metadata document",
@@ -77,7 +77,8 @@ protected override void SetResponses(OpenApiOperation operation)
}
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
index 2bedd562a..51f2cb085 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
@@ -31,7 +31,7 @@ public NavigationPropertyDeleteOperationHandler(OpenApiDocument document):base(d
///
public override HttpMethod OperationType => HttpMethod.Delete;
- private DeleteRestrictionsType _deleteRestriction;
+ private DeleteRestrictionsType? _deleteRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -44,12 +44,12 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Delete navigation property " + NavigationProperty.Name + " for " + NavigationSource.Name;
+ string placeHolder = "Delete navigation property " + NavigationProperty?.Name + " for " + NavigationSource?.Name;
operation.Summary = _deleteRestriction?.Description ?? placeHolder;
operation.Description = _deleteRestriction?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is { Settings.EnableOperationId: true})
{
string prefix = "Delete";
operation.OperationId = GetOperationId(prefix);
@@ -63,6 +63,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ operation.Parameters ??= [];
operation.Parameters.Add(new OpenApiParameter
{
Name = "If-Match",
@@ -78,19 +79,19 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetSecurity(OpenApiOperation operation)
{
- if (_deleteRestriction == null)
+ if (_deleteRestriction?.Permissions == null)
{
return;
}
- operation.Security = Context.CreateSecurityRequirements(_deleteRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_deleteRestriction.Permissions, _document).ToList() ?? [];
}
///
protected override void SetResponses(OpenApiOperation operation)
{
// Response for Delete methods should be 204 No Content
- OpenApiConvertSettings settings = Context.Settings.Clone();
+ OpenApiConvertSettings settings = Context?.Settings.Clone() ?? new();
settings.UseSuccessStatusCodeRange = false;
operation.AddErrorResponses(settings, _document, true);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs
index 0d01c013d..49a271198 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs
@@ -3,12 +3,14 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
@@ -37,7 +39,7 @@ public NavigationPropertyGetOperationHandler(OpenApiDocument document) : base(do
///
public override HttpMethod OperationType => HttpMethod.Get;
- private ReadRestrictionsType _readRestriction;
+ private ReadRestrictionsType? _readRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -50,13 +52,13 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Get " + NavigationProperty.Name + " from " + NavigationSource.Name;
+ string placeHolder = "Get " + NavigationProperty?.Name + " from " + NavigationSource?.Name;
operation.Summary = (LastSegmentIsKeySegment ? _readRestriction?.ReadByKeyRestrictions?.Description : _readRestriction?.Description) ?? placeHolder;
operation.Description = (LastSegmentIsKeySegment ? _readRestriction?.ReadByKeyRestrictions?.LongDescription : _readRestriction?.LongDescription)
- ?? Context.Model.GetDescriptionAnnotation(NavigationProperty);
+ ?? Context?.Model.GetDescriptionAnnotation(NavigationProperty);
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is { Settings.EnableOperationId: true })
{
string prefix = "Get";
if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
@@ -72,18 +74,16 @@ protected override void SetBasicInfo(OpenApiOperation operation)
protected override void SetExtensions(OpenApiOperation operation)
{
- if (Context.Settings.EnablePagination)
+ if (Context is { Settings.EnablePagination: true } && !LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
{
- if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
+ var extension = new JsonObject
{
- JsonObject extension = new JsonObject
- {
- { "nextLinkName", "@odata.nextLink"},
- { "operationName", Context.Settings.PageableOperationName}
- };
+ { "nextLinkName", "@odata.nextLink"},
+ { "operationName", Context.Settings.PageableOperationName}
+ };
- operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
- }
+ operation.Extensions ??= new Dictionary();
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
base.SetExtensions(operation);
@@ -92,10 +92,10 @@ protected override void SetExtensions(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- IDictionary links = null;
- if (Context.Settings.ShowLinks)
+ IDictionary? links = null;
+ if (Context is { Settings.ShowLinks: true } && NavigationProperty is not null && Path is not null)
{
- string operationId = GetOperationId();
+ var operationId = GetOperationId();
links = Context.CreateLinks(entityType: NavigationProperty.ToEntityType(), entityName: NavigationProperty.Name,
entityKind: NavigationProperty.PropertyKind.ToString(), path: Path, parameters: PathParameters,
@@ -107,17 +107,17 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponseReference($"{NavigationProperty.ToEntityType().FullName()}{Constants.CollectionSchemaSuffix}", _document)
}
};
}
else
{
- IOpenApiSchema schema = null;
+ IOpenApiSchema? schema = null;
var entityType = NavigationProperty.ToEntityType();
- if (Context.Settings.EnableDerivedTypesReferencesForResponses)
+ if (Context is { Settings.EnableDerivedTypesReferencesForResponses: true })
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(entityType, Context.Model, _document);
}
@@ -127,7 +127,7 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponse
{
Description = "Retrieved navigation property",
@@ -147,7 +147,8 @@ protected override void SetResponses(OpenApiOperation operation)
};
}
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -157,73 +158,71 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- OpenApiParameter selectParameter = Context.CreateSelect(TargetPath, NavigationProperty.ToEntityType())
- ?? Context.CreateSelect(NavigationProperty);
-
- OpenApiParameter expandParameter = Context.CreateExpand(TargetPath, NavigationProperty.ToEntityType())
- ?? Context.CreateExpand(NavigationProperty);
+ if (Context is null)
+ {
+ return;
+ }
- if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
+ var (selectParameter, expandParameter) = (string.IsNullOrEmpty(TargetPath), NavigationProperty) switch
+ {
+ (false, not null) when NavigationProperty.ToEntityType() is {} entityType =>
+ (Context.CreateSelect(TargetPath!, entityType) ?? Context.CreateSelect(NavigationProperty),
+ Context.CreateExpand(TargetPath!, entityType) ?? Context.CreateExpand(NavigationProperty)),
+ (true, not null) => (Context.CreateSelect(NavigationProperty), Context.CreateExpand(NavigationProperty)),
+ _ => (null, null),
+ };
+
+ var parametersToAdd = new List();
+ if (!LastSegmentIsKeySegment && NavigationProperty?.TargetMultiplicity() == EdmMultiplicity.Many)
{
// Need to verify that TopSupported or others should be applied to navigation source.
// So, how about for the navigation property.
- var parameter = Context.CreateTop(TargetPath, _document) ?? Context.CreateTop(NavigationProperty, _document);
- if (parameter != null)
- {
- operation.Parameters.Add(parameter);
- }
-
- parameter = Context.CreateSkip(TargetPath, _document) ?? Context.CreateSkip(NavigationProperty, _document);
- if (parameter != null)
- {
- operation.Parameters.Add(parameter);
- }
-
- parameter = Context.CreateSearch(TargetPath, _document) ?? Context.CreateSearch(NavigationProperty, _document);
- if (parameter != null)
- {
- operation.Parameters.Add(parameter);
- }
-
- parameter = Context.CreateFilter(TargetPath, _document) ?? Context.CreateFilter(NavigationProperty, _document);
- if (parameter != null)
- {
- operation.Parameters.Add(parameter);
- }
-
- parameter = Context.CreateCount(TargetPath, _document) ?? Context.CreateCount(NavigationProperty, _document);
- if (parameter != null)
+ AddParameterIfExists(parametersToAdd, Context.CreateTop, Context.CreateTop);
+ AddParameterIfExists(parametersToAdd, Context.CreateSkip, Context.CreateSkip);
+ AddParameterIfExists(parametersToAdd, Context.CreateSearch, Context.CreateSearch);
+ AddParameterIfExists(parametersToAdd, Context.CreateFilter, Context.CreateFilter);
+ AddParameterIfExists(parametersToAdd, Context.CreateCount, Context.CreateCount);
+
+ var orderByParameter = (string.IsNullOrEmpty(TargetPath), NavigationProperty) switch
+ {
+ (false, not null) when NavigationProperty.ToEntityType() is {} entityType =>
+ Context.CreateOrderBy(TargetPath!, entityType),
+ (true, not null) => Context.CreateOrderBy(NavigationProperty),
+ _ => null,
+ };
+ if (orderByParameter != null)
{
- operation.Parameters.Add(parameter);
+ parametersToAdd.Add(orderByParameter);
}
+ }
- parameter = Context.CreateOrderBy(TargetPath, NavigationProperty.ToEntityType()) ?? Context.CreateOrderBy(NavigationProperty);
- if (parameter != null)
- {
- operation.Parameters.Add(parameter);
- }
+ if (selectParameter != null)
+ {
+ parametersToAdd.Add(selectParameter);
+ }
- if (selectParameter != null)
- {
- operation.Parameters.Add(selectParameter);
- }
+ if (expandParameter != null)
+ {
+ parametersToAdd.Add(expandParameter);
+ }
- if (expandParameter != null)
- {
- operation.Parameters.Add(expandParameter);
- }
+ if (parametersToAdd.Count > 0)
+ {
+ if (operation.Parameters is null) operation.Parameters = parametersToAdd;
+ else parametersToAdd.ForEach(p => operation.Parameters.Add(p));
}
- else
+ }
+ private void AddParameterIfExists(List parameters,
+ Func createParameterFromPath,
+ Func createParameterFromProperty)
+ {
+ if (!string.IsNullOrEmpty(TargetPath) && createParameterFromPath(TargetPath, _document) is {} parameterFromPath)
{
- if (selectParameter != null)
- {
- operation.Parameters.Add(selectParameter);
- }
-
- if (expandParameter != null)
- {
- operation.Parameters.Add(expandParameter);
- }
+ parameters.Add(parameterFromPath);
+ }
+ else if (NavigationProperty is not null && createParameterFromProperty(NavigationProperty, _document) is {} parameterFromProperty)
+ {
+ parameters.Add(parameterFromProperty);
}
}
@@ -240,7 +239,8 @@ protected override void SetSecurity(OpenApiOperation operation)
readBase = _readRestriction.ReadByKeyRestrictions;
}
- operation.Security = Context.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
+ if (readBase.Permissions is not null)
+ operation.Security = Context?.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs
index 445dd4074..d55a0ec2c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs
@@ -5,6 +5,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
@@ -34,17 +35,17 @@ protected NavigationPropertyOperationHandler(OpenApiDocument document):base(docu
///
/// Gets the navigation property.
///
- protected IEdmNavigationProperty NavigationProperty { get; private set; }
+ protected IEdmNavigationProperty? NavigationProperty { get; private set; }
///
/// Gets the navigation source.
///
- protected IEdmNavigationSource NavigationSource { get; private set; }
+ protected IEdmNavigationSource? NavigationSource { get; private set; }
///
/// Gets the navigation restriction.
///
- protected NavigationPropertyRestriction Restriction { get; private set; }
+ protected NavigationPropertyRestriction? Restriction { get; private set; }
///
/// Gets a bool value indicating whether the last segment is a key segment.
@@ -66,41 +67,39 @@ protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
- NavigationSource = navigationSourceSegment.NavigationSource;
+ ODataNavigationSourceSegment? navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
+ NavigationSource = navigationSourceSegment?.NavigationSource;
LastSegmentIsKeySegment = path.LastSegment is ODataKeySegment;
LastSegmentIsRefSegment = path.LastSegment is ODataRefSegment;
- SecondLastSegmentIsKeySegment = Path.Segments.Reverse().Skip(1).Take(1).Single().Kind == ODataSegmentKind.Key;
+ SecondLastSegmentIsKeySegment = Path?.Segments.Reverse().Skip(1).Take(1).Single().Kind == ODataSegmentKind.Key;
NavigationProperty = path.OfType().Last().NavigationProperty;
- IEdmEntitySet entitySet = NavigationSource as IEdmEntitySet;
- IEdmSingleton singleton = NavigationSource as IEdmSingleton;
+ var navigation = NavigationSource switch {
+ IEdmEntitySet entitySet => Context?.Model.GetRecord(entitySet, CapabilitiesConstants.NavigationRestrictions),
+ IEdmSingleton singleton => Context?.Model.GetRecord(singleton, CapabilitiesConstants.NavigationRestrictions),
+ _ => null
+ };
- NavigationRestrictionsType navigation;
- if (entitySet != null)
- {
- navigation = Context.Model.GetRecord(entitySet, CapabilitiesConstants.NavigationRestrictions);
- }
- else
- {
- navigation = Context.Model.GetRecord(singleton, CapabilitiesConstants.NavigationRestrictions);
- }
+ var navPropertyPath = Path?.NavigationPropertyPath();
- Restriction = navigation?.RestrictedProperties?.FirstOrDefault(r => r.NavigationProperty != null && r.NavigationProperty == Path.NavigationPropertyPath())
- ?? Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.NavigationRestrictions)?.RestrictedProperties?.FirstOrDefault();
+ Restriction = navigation?.RestrictedProperties?.FirstOrDefault(r => r.NavigationProperty != null && r.NavigationProperty == navPropertyPath)
+ ?? Context?.Model.GetRecord(NavigationProperty, CapabilitiesConstants.NavigationRestrictions)?.RestrictedProperties?.FirstOrDefault();
}
///
protected override void SetTags(OpenApiOperation operation)
{
- string name = EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context);
- Context.AddExtensionToTag(name, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
- {
- Name = name
- });
- operation.Tags ??= new HashSet();
- operation.Tags.Add(new OpenApiTagReference(name, _document));
+ if (Context is not null && Path is not null)
+ {
+ string name = EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context);
+ Context.AddExtensionToTag(name, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = name
+ });
+ operation.Tags ??= new HashSet();
+ operation.Tags.Add(new OpenApiTagReference(name, _document));
+ }
base.SetTags(operation);
}
@@ -108,23 +107,28 @@ protected override void SetTags(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("operation"));
base.SetExtensions(operation);
}
- internal string GetOperationId(string prefix = null)
- {
+ internal string? GetOperationId(string? prefix = null)
+ {
+ if (Context is null || Path is null)
+ {
+ return null;
+ }
return EdmModelHelper.GenerateNavigationPropertyPathOperationId(Path, Context, prefix);
}
///
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs)
+ if (Context is {Settings.ShowExternalDocs: true} && !string.IsNullOrEmpty(CustomLinkRel))
{
- var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(NavigationProperty, CustomLinkRel);
+ var externalDocs = (string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetLinkRecord(TargetPath, CustomLinkRel)) ??
+ (NavigationProperty is null ? null : Context.Model.GetLinkRecord(NavigationProperty, CustomLinkRel));
if (externalDocs != null)
{
@@ -143,48 +147,61 @@ protected override void SetExternalDocs(OpenApiOperation operation)
///
/// The fully qualified restriction annotation term.
/// The restriction annotation, or null if not available.
- protected IRecord GetRestrictionAnnotation(string annotationTerm)
+ protected IRecord? GetRestrictionAnnotation(string annotationTerm)
{
+ if (Context is null) return null;
switch (annotationTerm)
{
case CapabilitiesConstants.ReadRestrictions:
- var readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ var readRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
readRestrictions?.MergePropertiesIfNull(Restriction?.ReadRestrictions);
readRestrictions ??= Restriction?.ReadRestrictions;
- var navPropReadRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.ReadRestrictions);
- readRestrictions?.MergePropertiesIfNull(navPropReadRestrictions);
- readRestrictions ??= navPropReadRestrictions;
+ if (NavigationProperty is not null)
+ {
+ var navPropReadRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.ReadRestrictions);
+ readRestrictions?.MergePropertiesIfNull(navPropReadRestrictions);
+ readRestrictions ??= navPropReadRestrictions;
+ }
return readRestrictions;
case CapabilitiesConstants.UpdateRestrictions:
- var updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+ var updateRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
updateRestrictions?.MergePropertiesIfNull(Restriction?.UpdateRestrictions);
updateRestrictions ??= Restriction?.UpdateRestrictions;
- var navPropUpdateRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.UpdateRestrictions);
- updateRestrictions?.MergePropertiesIfNull(navPropUpdateRestrictions);
- updateRestrictions ??= navPropUpdateRestrictions;
+ if (NavigationProperty is not null)
+ {
+ var navPropUpdateRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.UpdateRestrictions);
+ updateRestrictions?.MergePropertiesIfNull(navPropUpdateRestrictions);
+ updateRestrictions ??= navPropUpdateRestrictions;
+ }
return updateRestrictions;
case CapabilitiesConstants.InsertRestrictions:
- var insertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
+ var insertRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
insertRestrictions?.MergePropertiesIfNull(Restriction?.InsertRestrictions);
insertRestrictions ??= Restriction?.InsertRestrictions;
- var navPropInsertRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.InsertRestrictions);
- insertRestrictions?.MergePropertiesIfNull(navPropInsertRestrictions);
- insertRestrictions ??= navPropInsertRestrictions;
+ if (NavigationProperty is not null)
+ {
+ var navPropInsertRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.InsertRestrictions);
+ insertRestrictions?.MergePropertiesIfNull(navPropInsertRestrictions);
+ insertRestrictions ??= navPropInsertRestrictions;
+ }
return insertRestrictions;
case CapabilitiesConstants.DeleteRestrictions:
- var deleteRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
+ var deleteRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
deleteRestrictions?.MergePropertiesIfNull(Restriction?.DeleteRestrictions);
deleteRestrictions ??= Restriction?.DeleteRestrictions;
- var navPropDeleteRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.DeleteRestrictions);
- deleteRestrictions?.MergePropertiesIfNull(navPropDeleteRestrictions);
- deleteRestrictions ??= navPropDeleteRestrictions;
+ if (NavigationProperty is not null)
+ {
+ var navPropDeleteRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.DeleteRestrictions);
+ deleteRestrictions?.MergePropertiesIfNull(navPropDeleteRestrictions);
+ deleteRestrictions ??= navPropDeleteRestrictions;
+ }
return deleteRestrictions;
default:
@@ -193,7 +210,7 @@ protected IRecord GetRestrictionAnnotation(string annotationTerm)
}
}
- protected IDictionary GetContent(IOpenApiSchema schema = null, IEnumerable mediaTypes = null)
+ protected Dictionary GetContent(IOpenApiSchema? schema = null, IEnumerable? mediaTypes = null)
{
schema ??= GetOpenApiSchema();
var content = new Dictionary();
@@ -215,7 +232,7 @@ protected IDictionary GetContent(IOpenApiSchema schema
{
Schema = schema
});
- };
+ }
return content;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs
index 065fcfe44..de3e656bb 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs
@@ -32,7 +32,7 @@ public NavigationPropertyPostOperationHandler(OpenApiDocument document):base(doc
///
public override HttpMethod OperationType => HttpMethod.Post;
- private InsertRestrictionsType _insertRestriction;
+ private InsertRestrictionsType? _insertRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -45,12 +45,12 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Create new navigation property to " + NavigationProperty.Name + " for " + NavigationSource.Name;
+ string placeHolder = "Create new navigation property to " + NavigationProperty?.Name + " for " + NavigationSource?.Name;
operation.Summary = _insertRestriction?.Description ?? placeHolder;
operation.Description = _insertRestriction?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
string prefix = "Create";
operation.OperationId = GetOperationId(prefix);
@@ -62,12 +62,9 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetRequestBody(OpenApiOperation operation)
{
- OpenApiSchema schema = null;
-
- if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
- {
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model, _document);
- }
+ var schema = Context is {Settings.EnableDerivedTypesReferencesForRequestBody: true} ?
+ EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model, _document) :
+ null;
operation.RequestBody = new OpenApiRequestBody
{
@@ -82,17 +79,14 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- OpenApiSchema schema = null;
-
- if (Context.Settings.EnableDerivedTypesReferencesForResponses)
- {
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model, _document);
- }
+ var schema = Context is {Settings.EnableDerivedTypesReferencesForResponses: true} ?
+ EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model, _document) :
+ null;
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode201,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode201,
new OpenApiResponse
{
Description = "Created navigation property.",
@@ -100,7 +94,8 @@ protected override void SetResponses(OpenApiOperation operation)
}
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -112,7 +107,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_insertRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_insertRestriction.Permissions ?? [], _document).ToList() ?? [];
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs
index 3549480a6..566196258 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs
@@ -30,7 +30,7 @@ protected NavigationPropertyUpdateOperationHandler(OpenApiDocument document):bas
{
}
- private UpdateRestrictionsType _updateRestriction;
+ private UpdateRestrictionsType? _updateRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -43,12 +43,12 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Update the navigation property " + NavigationProperty.Name + " in " + NavigationSource.Name;
+ string placeHolder = "Update the navigation property " + NavigationProperty?.Name + " in " + NavigationSource?.Name;
operation.Summary = _updateRestriction?.Description ?? placeHolder;
operation.Description = _updateRestriction?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
string prefix = OperationType == HttpMethod.Patch ? "Update" : "Set";
operation.OperationId = GetOperationId(prefix);
@@ -60,11 +60,9 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetRequestBody(OpenApiOperation operation)
{
- OpenApiSchema schema = null;
- if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
- {
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model, _document);
- }
+ var schema = Context is { Settings.EnableDerivedTypesReferencesForRequestBody: true } ?
+ EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model, _document) :
+ null;
operation.RequestBody = new OpenApiRequestBody
{
@@ -79,18 +77,19 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
base.SetResponses(operation);
}
protected override void SetSecurity(OpenApiOperation operation)
{
- if (_updateRestriction == null)
+ if (_updateRestriction?.Permissions == null)
{
return;
}
- operation.Security = Context.CreateSecurityRequirements(_updateRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_updateRestriction.Permissions, _document).ToList() ?? [];
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs
index 4b6555087..bff2cf5f0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs
@@ -11,6 +11,7 @@
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
@@ -42,7 +43,7 @@ public ODataTypeCastGetOperationHandler(OpenApiDocument document):base(document)
/// Gets/sets the segment before cast.
/// this segment could be "entity set", "Collection property", etc.
///
- internal ODataSegment SecondLastSegment { get; set; }
+ internal ODataSegment? SecondLastSegment { get; set; }
private bool isKeySegment;
@@ -58,18 +59,18 @@ private bool IsSingleElement
entitySet == null);
}
- private NavigationPropertyRestriction restriction;
- private IEdmSingleton singleton;
- private IEdmEntitySet entitySet;
- private IEdmNavigationProperty navigationProperty;
- private IEdmStructuredType parentStructuredType;
- private IEdmSchemaElement ParentSchemaElement => parentStructuredType as IEdmSchemaElement;
- private IEdmStructuredType targetStructuredType;
- private IEdmSchemaElement TargetSchemaElement => targetStructuredType as IEdmSchemaElement;
+ private NavigationPropertyRestriction? restriction;
+ private IEdmSingleton? singleton;
+ private IEdmEntitySet? entitySet;
+ private IEdmNavigationProperty? navigationProperty;
+ private IEdmStructuredType? parentStructuredType;
+ private IEdmSchemaElement? ParentSchemaElement => parentStructuredType as IEdmSchemaElement;
+ private IEdmStructuredType? targetStructuredType;
+ private IEdmSchemaElement? TargetSchemaElement => targetStructuredType as IEdmSchemaElement;
private const int SecondLastSegmentIndex = 2;
private bool isIndexedCollValuedNavProp = false;
- private IEdmNavigationSource navigationSource;
- private IEdmVocabularyAnnotatable annotatable;
+ private IEdmNavigationSource? navigationSource;
+ private IEdmVocabularyAnnotatable? annotatable;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -90,11 +91,13 @@ protected override void Initialize(ODataContext context, ODataPath path)
// get the last second segment
int count = path.Segments.Count;
if(count >= SecondLastSegmentIndex)
- SecondLastSegment = path.Segments.ElementAt(count - SecondLastSegmentIndex);
+ SecondLastSegment = path.Segments[count - SecondLastSegmentIndex];
- parentStructuredType = SecondLastSegment is ODataComplexPropertySegment complexSegment ? complexSegment.ComplexType : SecondLastSegment.EntityType;
- ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
- navigationSource = navigationSourceSegment.NavigationSource;
+ parentStructuredType = SecondLastSegment is ODataComplexPropertySegment complexSegment ? complexSegment.ComplexType : SecondLastSegment?.EntityType;
+ if (path.FirstSegment is ODataNavigationSourceSegment navigationSourceSegment)
+ {
+ navigationSource = navigationSourceSegment.NavigationSource;
+ }
if (SecondLastSegment is ODataNavigationPropertySegment navigationPropertySegment)
{
@@ -107,7 +110,7 @@ protected override void Initialize(ODataContext context, ODataPath path)
else if (SecondLastSegment is ODataKeySegment)
{
isKeySegment = true;
- var thirdLastSegment = path.Segments.ElementAt(count - SecondLastSegmentIndex - 1);
+ var thirdLastSegment = path.Segments[count - SecondLastSegmentIndex - 1];
if (thirdLastSegment is ODataNavigationPropertySegment navigationPropertySegment1)
{
isIndexedCollValuedNavProp = true;
@@ -137,20 +140,21 @@ private void SetNavigationPropertyAndRestrictionFromNavigationSegment(ODataNavig
{
navigationProperty = navigationPropertySegment.NavigationProperty;
annotatable = navigationProperty;
- var navigationPropertyPath = string.Join("/",
- Path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment
- || s is ODataStreamContentSegment || s is ODataStreamPropertySegment)).Select(e => e.Identifier));
- if(path.FirstSegment is ODataNavigationSourceSegment navigationSourceSegment)
+ if(path.FirstSegment is ODataNavigationSourceSegment navigationSourceSegment &&
+ Context is not null)
{
- NavigationRestrictionsType navigation = navigationSourceSegment.NavigationSource switch {
+ NavigationRestrictionsType? navigation = navigationSourceSegment.NavigationSource switch {
IEdmEntitySet eSet => Context.Model.GetRecord(eSet, CapabilitiesConstants.NavigationRestrictions),
IEdmSingleton single => Context.Model.GetRecord(single, CapabilitiesConstants.NavigationRestrictions),
_ => null
};
- if (navigation?.RestrictedProperties != null)
+ if (navigation?.RestrictedProperties != null && Path is not null)
{
+ var navigationPropertyPath = string.Join("/",
+ Path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment
+ || s is ODataStreamContentSegment || s is ODataStreamPropertySegment)).Select(e => e.Identifier));
restriction = navigation.RestrictedProperties.FirstOrDefault(r => r.NavigationProperty != null && r.NavigationProperty == navigationPropertyPath);
}
}
@@ -170,16 +174,16 @@ private void SetAnnotatableRestrictionFromNavigationSourceSegment(ODataNavigatio
singleton = sTon;
}
- SetRestrictionFromAnnotatable(annotatable);
+ SetRestrictionFromAnnotatable();
}
- private void SetRestrictionFromAnnotatable(IEdmVocabularyAnnotatable annotatable)
+ private void SetRestrictionFromAnnotatable()
{
- if (this.annotatable == null)
+ if (annotatable == null)
return;
- NavigationRestrictionsType navigation = Context.Model.GetRecord(annotatable, CapabilitiesConstants.NavigationRestrictions);
+ var navigation = Context?.Model.GetRecord(annotatable, CapabilitiesConstants.NavigationRestrictions);
if (navigation?.RestrictedProperties != null)
{
restriction = navigation.RestrictedProperties.FirstOrDefault(r => r.NavigationProperty == null);
@@ -189,7 +193,7 @@ private void SetRestrictionFromAnnotatable(IEdmVocabularyAnnotatable annotatable
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
- ReadRestrictionsType _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ var _readRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
// Summary
string placeHolder = IsSingleElement
@@ -199,7 +203,9 @@ protected override void SetBasicInfo(OpenApiOperation operation)
operation.Description = _readRestrictions?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is { Settings.EnableOperationId: true } &&
+ Path is not null &&
+ TargetSchemaElement is not null)
operation.OperationId = EdmModelHelper.GenerateODataTypeCastPathOperationIdPrefix(Path, Context) + $".As{Utils.UpperFirstChar(TargetSchemaElement.Name)}-{Path.GetPathHash(Context.Settings)}";
base.SetBasicInfo(operation);
@@ -210,9 +216,9 @@ protected override void SetResponses(OpenApiOperation operation)
{
if (IsSingleElement)
{
- IOpenApiSchema schema = null;
+ IOpenApiSchema? schema = null;
- if (Context.Settings.EnableDerivedTypesReferencesForResponses)
+ if (Context is { Settings.EnableDerivedTypesReferencesForResponses: true } && targetStructuredType is not null)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(targetStructuredType, Context.Model, _document);
}
@@ -229,7 +235,8 @@ protected override void SetResponses(OpenApiOperation operation)
SetCollectionResponse(operation, TargetSchemaElement.FullName());
}
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -237,23 +244,26 @@ protected override void SetResponses(OpenApiOperation operation)
///
protected override void SetTags(OpenApiOperation operation)
{
- string tagName = null;
+ if (Context is null)
+ return;
+ string? tagName = null;
operation.Tags ??= new HashSet();
- if (SecondLastSegment is ODataNavigationPropertySegment || isIndexedCollValuedNavProp)
+ if ((SecondLastSegment is ODataNavigationPropertySegment || isIndexedCollValuedNavProp) &&
+ Path is not null)
{
tagName = EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context);
}
else if ((SecondLastSegment is ODataKeySegment && !isIndexedCollValuedNavProp)
|| (SecondLastSegment is ODataNavigationSourceSegment))
{
- var singletonNavigationSource = navigationSource as IEdmSingleton;
-
- tagName = navigationSource is IEdmEntitySet entitySetNavigationSource
- ? entitySetNavigationSource.Name + "." + entitySetNavigationSource.EntityType.Name
- : singletonNavigationSource.Name + "." + singletonNavigationSource.EntityType.Name;
+ tagName = navigationSource switch {
+ IEdmEntitySet entitySetNavigationSource => entitySetNavigationSource.Name + "." + entitySetNavigationSource.EntityType.Name,
+ IEdmSingleton singletonNavigationSource => singletonNavigationSource.Name + "." + singletonNavigationSource.EntityType.Name,
+ _ => null
+ };
}
- else if (SecondLastSegment is ODataComplexPropertySegment)
+ else if (SecondLastSegment is ODataComplexPropertySegment && Path is not null)
{
tagName = EdmModelHelper.GenerateComplexPropertyPathTagName(Path, Context);
}
@@ -277,14 +287,19 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ if (Context is null)
+ return;
+
+ operation.Parameters ??= [];
+
if(navigationProperty != null) {
if (IsSingleElement)
{
- new OpenApiParameter[] {
- Context.CreateSelect(TargetPath, navigationProperty.ToEntityType()) ?? Context.CreateSelect(navigationProperty),
- Context.CreateExpand(TargetPath, navigationProperty.ToEntityType()) ?? Context.CreateExpand(navigationProperty),
+ new IOpenApiParameter?[] {
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSelect(TargetPath, navigationProperty.ToEntityType())) ?? Context.CreateSelect(navigationProperty),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateExpand(TargetPath, navigationProperty.ToEntityType())) ?? Context.CreateExpand(navigationProperty),
}
- .Where(x => x != null)
+ .OfType()
.ToList()
.ForEach(p => operation.Parameters.Add(p));
}
@@ -292,12 +307,12 @@ protected override void SetParameters(OpenApiOperation operation)
{
GetParametersForAnnotableOfMany(navigationProperty)
.Union(
- new OpenApiParameter[] {
- Context.CreateOrderBy(TargetPath, navigationProperty.ToEntityType()) ?? Context.CreateOrderBy(navigationProperty),
- Context.CreateSelect(TargetPath, navigationProperty.ToEntityType()) ?? Context.CreateSelect(navigationProperty),
- Context.CreateExpand(TargetPath, navigationProperty.ToEntityType()) ?? Context.CreateExpand(navigationProperty),
- })
- .Where(x => x != null)
+ [
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateOrderBy(TargetPath, navigationProperty.ToEntityType())) ?? Context.CreateOrderBy(navigationProperty),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSelect(TargetPath, navigationProperty.ToEntityType())) ?? Context.CreateSelect(navigationProperty),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateExpand(TargetPath, navigationProperty.ToEntityType())) ?? Context.CreateExpand(navigationProperty),
+ ])
+ .OfType()
.ToList()
.ForEach(p => operation.Parameters.Add(p));
}
@@ -306,11 +321,11 @@ protected override void SetParameters(OpenApiOperation operation)
{
if(IsSingleElement)
{
- new IOpenApiParameter[] {
- Context.CreateSelect(TargetPath, entitySet.EntityType) ?? Context.CreateSelect(entitySet),
- Context.CreateExpand(TargetPath, entitySet.EntityType) ?? Context.CreateExpand(entitySet),
+ new IOpenApiParameter?[] {
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSelect(TargetPath, entitySet.EntityType)) ?? Context.CreateSelect(entitySet),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateExpand(TargetPath, entitySet.EntityType)) ?? Context.CreateExpand(entitySet),
}
- .Where(x => x != null)
+ .OfType()
.ToList()
.ForEach(operation.Parameters.Add);
}
@@ -319,28 +334,30 @@ protected override void SetParameters(OpenApiOperation operation)
GetParametersForAnnotableOfMany(entitySet)
.Union(
[
- Context.CreateOrderBy(TargetPath, entitySet.EntityType) ?? Context.CreateOrderBy(entitySet),
- Context.CreateSelect(TargetPath, entitySet.EntityType) ?? Context.CreateSelect(entitySet),
- Context.CreateExpand(TargetPath, entitySet.EntityType) ?? Context.CreateExpand(entitySet),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateOrderBy(TargetPath, entitySet.EntityType)) ?? Context.CreateOrderBy(entitySet),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSelect(TargetPath, entitySet.EntityType)) ?? Context.CreateSelect(entitySet),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateExpand(TargetPath, entitySet.EntityType)) ?? Context.CreateExpand(entitySet),
])
- .Where(x => x != null)
+ .OfType()
.ToList()
.ForEach(p => operation.Parameters.Add(p));
}
}
else if(singleton != null)
{
- new OpenApiParameter[] {
- Context.CreateSelect(TargetPath, singleton.EntityType) ?? Context.CreateSelect(singleton),
- Context.CreateExpand(TargetPath, singleton.EntityType) ?? Context.CreateExpand(singleton),
+ new IOpenApiParameter?[] {
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSelect(TargetPath, singleton.EntityType)) ?? Context.CreateSelect(singleton),
+ (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateExpand(TargetPath, singleton.EntityType)) ?? Context.CreateExpand(singleton),
}
- .Where(x => x != null)
+ .OfType()
.ToList()
.ForEach(p => operation.Parameters.Add(p));
}
}
- private IEnumerable GetParametersForAnnotableOfMany(IEdmVocabularyAnnotatable annotable)
+ private IEnumerable GetParametersForAnnotableOfMany(IEdmVocabularyAnnotatable annotable)
{
+ if (Context is null)
+ return [];
// Need to verify that TopSupported or others should be applied to navigation source.
// So, how about for the navigation property.
return [
@@ -354,19 +371,17 @@ private IEnumerable GetParametersForAnnotableOfMany(IEdmVocab
protected override void SetSecurity(OpenApiOperation operation)
{
- if (restriction == null || restriction.ReadRestrictions == null)
+ if (restriction is not {ReadRestrictions.Permissions: not null})
{
return;
}
- ReadRestrictionsBase readBase = restriction.ReadRestrictions;
-
- operation.Security = Context.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(restriction.ReadRestrictions.Permissions, _document).ToList();
}
protected override void SetExtensions(OpenApiOperation operation)
{
- if (Context.Settings.EnablePagination && !IsSingleElement)
+ if (Context is { Settings.EnablePagination: true } && !IsSingleElement)
{
JsonObject extension = new()
{
@@ -374,6 +389,7 @@ protected override void SetExtensions(OpenApiOperation operation)
{ "operationName", Context.Settings.PageableOperationName}
};
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
@@ -385,10 +401,15 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
if (annotatable == null)
return;
- ReadRestrictionsType readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- var annotatableReadRestrictions = Context.Model.GetRecord(annotatable, CapabilitiesConstants.ReadRestrictions);
- readRestrictions?.MergePropertiesIfNull(annotatableReadRestrictions);
- readRestrictions ??= annotatableReadRestrictions;
+ if (Context is null)
+ return;
+
+ var readRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (Context.Model.GetRecord(annotatable, CapabilitiesConstants.ReadRestrictions) is {} annotatableReadRestrictions)
+ {
+ readRestrictions?.MergePropertiesIfNull(annotatableReadRestrictions);
+ readRestrictions ??= annotatableReadRestrictions;
+ }
if (readRestrictions == null)
{
@@ -408,7 +429,10 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs && Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) is LinkType externalDocs)
+ if (Context is { Settings.ShowExternalDocs: true } &&
+ !string.IsNullOrEmpty(CustomLinkRel) &&
+ !string.IsNullOrEmpty(TargetPath) &&
+ Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) is LinkType externalDocs)
{
operation.ExternalDocs = new OpenApiExternalDocs()
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
index 4f27692c6..f09ff552b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.MicrosoftExtensions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
@@ -37,17 +38,17 @@ protected OperationHandler(OpenApiDocument document)
///
public abstract HttpMethod OperationType { get; }
- protected IDictionary> ParameterMappings;
+ protected IDictionary>? ParameterMappings;
///
/// The path parameters in the path
///
- protected IList PathParameters;
+ protected IList? PathParameters;
///
/// The string representation of the Edm target path for annotations.
///
- protected string TargetPath;
+ protected string? TargetPath;
///
public virtual OpenApiOperation CreateOperation(ODataContext context, ODataPath path)
@@ -96,38 +97,43 @@ will be used in the Responses when creating Links.
private void SetDeprecation(OpenApiOperation operation)
{
- if (operation != null && Context.Settings.EnableDeprecationInformation)
+ if (operation is null ||
+ Context is null ||
+ !Context.Settings.EnableDeprecationInformation ||
+ Path is null)
{
- var deprecationInfo = Path.SelectMany(x => x.GetAnnotables())
- .SelectMany(x => Context.GetDeprecationInformations(x))
- .Where(x => x != null)
- .OrderByDescending(x => x.Date)
- .ThenByDescending(x => x.RemovalDate)
- .FirstOrDefault();
-
- if (deprecationInfo != null)
- {
- operation.Deprecated = true;
- var deprecationDetails = deprecationInfo.GetOpenApiExtension();
- operation.Extensions.Add(OpenApiDeprecationExtension.Name, deprecationDetails);
- }
+ return;
+ }
+ var deprecationInfo = Path.SelectMany(x => x.GetAnnotables())
+ .SelectMany(x => Context.GetDeprecationInformations(x))
+ .Where(x => x != null)
+ .OrderByDescending(x => x.Date)
+ .ThenByDescending(x => x.RemovalDate)
+ .FirstOrDefault();
+
+ if (deprecationInfo != null)
+ {
+ operation.Deprecated = true;
+ var deprecationDetails = deprecationInfo.GetOpenApiExtension();
+ operation.Extensions ??= new Dictionary();
+ operation.Extensions.Add(OpenApiDeprecationExtension.Name, deprecationDetails);
}
}
///
/// Gets the OData context.
///
- protected ODataContext Context { get; private set; }
+ protected ODataContext? Context { get; private set; }
///
/// Gets the OData path.
///
- protected ODataPath Path { get; private set; }
+ protected ODataPath? Path { get; private set; }
///
/// Gets the custom link relation type for path based on operation type
///
- protected string CustomLinkRel { get; set; }
+ protected string? CustomLinkRel { get; set; }
///
/// Initialize the handler.
@@ -175,12 +181,16 @@ protected virtual void SetRequestBody(OpenApiOperation operation)
/// The .
protected virtual void SetParameters(OpenApiOperation operation)
{
- PathParameters = Path.CreatePathParameters(Context, _document);
- if (!Context.Settings.DeclarePathParametersOnPathItem)
+ if (Context is not null && Path is not null)
{
- foreach (var parameter in PathParameters)
+ PathParameters = Path.CreatePathParameters(Context, _document);
+ if (!Context.Settings.DeclarePathParametersOnPathItem)
{
- operation.Parameters.AppendParameter(parameter);
+ operation.Parameters ??= [];
+ foreach (var parameter in PathParameters)
+ {
+ operation.Parameters.AppendParameter(parameter);
+ }
}
}
@@ -239,7 +249,7 @@ protected static void AppendCustomParameters(OpenApiOperation operation, IList
protected virtual void SetCustomLinkRelType()
{
- if (Context.Settings.CustomHttpMethodLinkRelMapping != null)
+ if (Context?.Settings.CustomHttpMethodLinkRelMapping is not null &&
+ Path is not null)
{
LinkRelKey? key = OperationType.ToString().ToLowerInvariant() switch
{
@@ -300,9 +312,8 @@ protected virtual void SetCustomLinkRelType()
_ => null,
};
- if (key != null)
+ if (key != null && key.HasValue && Context.Settings.CustomHttpMethodLinkRelMapping.TryGetValue(key.Value, out var linkRelValue))
{
- Context.Settings.CustomHttpMethodLinkRelMapping.TryGetValue((LinkRelKey)key, out string linkRelValue);
CustomLinkRel = linkRelValue;
}
}
@@ -316,7 +327,7 @@ internal void SetCollectionResponse(OpenApiOperation operation, string targetEle
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ (Context?.Settings.UseSuccessStatusCodeRange ?? false) ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponseReference($"{targetElementFullName}{Constants.CollectionSchemaSuffix}", _document)
}
};
@@ -330,7 +341,7 @@ internal void SetSingleResponse(OpenApiOperation operation, IOpenApiSchema schem
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ (Context?.Settings.UseSuccessStatusCodeRange ?? false) ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponse
{
Description = "Entity result.",
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs
index 9f65fedf8..ebb420d37 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs
@@ -16,7 +16,7 @@ namespace Microsoft.OpenApi.OData.Operation
internal class OperationHandlerProvider : IOperationHandlerProvider
{
///
- public IOperationHandler GetHandler(ODataPathKind pathKind, HttpMethod operationType, OpenApiDocument document)
+ public IOperationHandler? GetHandler(ODataPathKind pathKind, HttpMethod operationType, OpenApiDocument document)
{
return (pathKind, operationType.ToString().ToLowerInvariant()) switch
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs
index 5211b8657..dab9aadb0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs
@@ -29,7 +29,7 @@ public RefDeleteOperationHandler(OpenApiDocument document) : base(document)
}
///
public override HttpMethod OperationType => HttpMethod.Delete;
- private DeleteRestrictionsType _deleteRestriction;
+ private DeleteRestrictionsType? _deleteRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -42,15 +42,15 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Delete ref of navigation property " + NavigationProperty.Name + " for " + NavigationSource.Name;
+ string placeHolder = "Delete ref of navigation property " + NavigationProperty?.Name + " for " + NavigationSource?.Name;
operation.Summary = _deleteRestriction?.Description ?? placeHolder;
operation.Description = _deleteRestriction?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
string prefix = "DeleteRef";
- var segments = GetOperationId().Split('.').ToList();
+ var segments = GetOperationId()?.Split('.').ToList() ?? [];
if (SecondLastSegmentIsKeySegment)
{
@@ -73,6 +73,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+ operation.Parameters ??= [];
operation.Parameters.Add(new OpenApiParameter
{
Name = "If-Match",
@@ -86,7 +87,7 @@ protected override void SetParameters(OpenApiOperation operation)
// for collection, we should have @id in query
if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many &&
- Path.Segments.Reverse().Skip(1).First() is ODataNavigationPropertySegment)
+ Path?.Segments.Reverse().Skip(1).First() is ODataNavigationPropertySegment)
{
operation.Parameters.Add(new OpenApiParameter
{
@@ -105,19 +106,19 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetSecurity(OpenApiOperation operation)
{
- if (_deleteRestriction == null)
+ if (_deleteRestriction?.Permissions == null)
{
return;
}
- operation.Security = Context.CreateSecurityRequirements(_deleteRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_deleteRestriction.Permissions, _document).ToList();
}
///
protected override void SetResponses(OpenApiOperation operation)
{
// Response for Delete methods should be 204 No Content
- OpenApiConvertSettings settings = Context.Settings.Clone();
+ var settings = Context?.Settings.Clone() ?? new();
settings.UseSuccessStatusCodeRange = false;
operation.AddErrorResponses(settings, _document, true);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs
index 6f4138194..a70765b21 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs
@@ -9,6 +9,7 @@
using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
@@ -34,7 +35,7 @@ public RefGetOperationHandler(OpenApiDocument document) : base(document)
}
///
public override HttpMethod OperationType => HttpMethod.Get;
- private ReadRestrictionsType _readRestriction;
+ private ReadRestrictionsType? _readRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -47,13 +48,13 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Get ref of " + NavigationProperty.Name + " from " + NavigationSource.Name;
+ string placeHolder = "Get ref of " + NavigationProperty?.Name + " from " + NavigationSource?.Name;
operation.Summary = (LastSegmentIsKeySegment ? _readRestriction?.ReadByKeyRestrictions?.Description : _readRestriction?.Description) ?? placeHolder;
operation.Description = (LastSegmentIsKeySegment ? _readRestriction?.ReadByKeyRestrictions?.LongDescription : _readRestriction?.LongDescription)
- ?? Context.Model.GetDescriptionAnnotation(NavigationProperty);
+ ?? Context?.Model.GetDescriptionAnnotation(NavigationProperty);
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
string prefix = "GetRef";
if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
@@ -67,18 +68,16 @@ protected override void SetBasicInfo(OpenApiOperation operation)
protected override void SetExtensions(OpenApiOperation operation)
{
- if (Context.Settings.EnablePagination)
+ if (Context is { Settings.EnablePagination: true } && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
{
- if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
- {
- JsonObject extension = new JsonObject
+ JsonObject extension = new JsonObject
{
{ "nextLinkName", "@odata.nextLink"},
{ "operationName", Context.Settings.PageableOperationName}
};
- operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
- }
+ operation.Extensions ??= new Dictionary();
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
base.SetExtensions(operation);
@@ -92,7 +91,7 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponseReference($"String{Constants.CollectionSchemaSuffix}", _document)
}
};
@@ -104,10 +103,10 @@ protected override void SetResponses(OpenApiOperation operation)
// $ref returns string for the Uri?
Type = JsonSchemaType.String
};
- IDictionary links = null;
- if (Context.Settings.ShowLinks)
+ IDictionary? links = null;
+ if (Context is {Settings.ShowLinks: true} && NavigationProperty is not null && Path is not null)
{
- string operationId = GetOperationId();
+ var operationId = GetOperationId();
links = Context.CreateLinks(entityType: NavigationProperty.ToEntityType(), entityName: NavigationProperty.Name,
entityKind: NavigationProperty.PropertyKind.ToString(), parameters: PathParameters, path: Path,
@@ -117,7 +116,7 @@ protected override void SetResponses(OpenApiOperation operation)
operation.Responses = new OpenApiResponses
{
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
new OpenApiResponse
{
Description = "Retrieved navigation property link",
@@ -137,7 +136,8 @@ protected override void SetResponses(OpenApiOperation operation)
};
}
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -147,41 +147,48 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
+ if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many && Context is not null)
{
// Need to verify that TopSupported or others should be applied to navigaiton source.
// So, how about for the navigation property.
- var parameter = Context.CreateTop(TargetPath, _document) ?? Context.CreateTop(NavigationProperty, _document);
+ var parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateTop(TargetPath, _document)) ??
+ (NavigationProperty is null ? null : Context.CreateTop(NavigationProperty, _document));
+ operation.Parameters ??= [];
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateSkip(TargetPath, _document) ?? Context.CreateSkip(NavigationProperty, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSkip(TargetPath, _document)) ??
+ (NavigationProperty is null ? null : Context.CreateSkip(NavigationProperty, _document));
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateSearch(TargetPath, _document) ?? Context.CreateSearch(NavigationProperty, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateSearch(TargetPath, _document)) ??
+ (NavigationProperty is null ? null : Context.CreateSearch(NavigationProperty, _document));
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateFilter(TargetPath, _document) ?? Context.CreateFilter(NavigationProperty, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateFilter(TargetPath, _document)) ??
+ (NavigationProperty is null ? null : Context.CreateFilter(NavigationProperty, _document));
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateCount(TargetPath, _document) ?? Context.CreateCount(NavigationProperty, _document);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateCount(TargetPath, _document)) ??
+ (NavigationProperty is null ? null : Context.CreateCount(NavigationProperty, _document));
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateOrderBy(TargetPath, NavigationProperty.ToEntityType()) ?? Context.CreateOrderBy(NavigationProperty);
+ parameter = (string.IsNullOrEmpty(TargetPath) ? null : Context.CreateOrderBy(TargetPath, NavigationProperty.ToEntityType())) ??
+ (NavigationProperty is null ? null : Context.CreateOrderBy(NavigationProperty));
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -191,13 +198,12 @@ protected override void SetParameters(OpenApiOperation operation)
protected override void SetSecurity(OpenApiOperation operation)
{
- if (_readRestriction == null)
+ if (_readRestriction?.Permissions == null)
{
return;
}
- ReadRestrictionsBase readBase = _readRestriction;
- operation.Security = Context.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_readRestriction.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs
index 04c82e54b..228019c3a 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs
@@ -29,7 +29,7 @@ public RefPostOperationHandler(OpenApiDocument document) : base(document)
}
///
public override HttpMethod OperationType => HttpMethod.Post;
- private InsertRestrictionsType _insertRestriction;
+ private InsertRestrictionsType? _insertRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -42,12 +42,12 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Create new navigation property ref to " + NavigationProperty.Name + " for " + NavigationSource.Name;
+ string placeHolder = "Create new navigation property ref to " + NavigationProperty?.Name + " for " + NavigationSource?.Name;
operation.Summary = _insertRestriction?.Description ?? placeHolder;
operation.Description = _insertRestriction?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
string prefix = "CreateRef";
operation.OperationId = GetOperationId(prefix);
@@ -73,19 +73,20 @@ protected override void SetResponses(OpenApiOperation operation)
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
protected override void SetSecurity(OpenApiOperation operation)
{
- if (_insertRestriction == null)
+ if (_insertRestriction?.Permissions is null)
{
return;
}
- operation.Security = Context.CreateSecurityRequirements(_insertRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_insertRestriction.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs
index 984be2386..4d0e85cee 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs
@@ -29,7 +29,7 @@ public RefPutOperationHandler(OpenApiDocument document) : base(document)
}
///
public override HttpMethod OperationType => HttpMethod.Patch;
- private UpdateRestrictionsType _updateRestriction;
+ private UpdateRestrictionsType? _updateRestriction;
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -42,12 +42,12 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Description
- string placeHolder = "Update the ref of navigation property " + NavigationProperty.Name + " in " + NavigationSource.Name;
+ string placeHolder = "Update the ref of navigation property " + NavigationProperty?.Name + " in " + NavigationSource?.Name;
operation.Summary = _updateRestriction?.Description ?? placeHolder;
operation.Description = _updateRestriction?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true})
{
string prefix = "UpdateRef";
operation.OperationId = GetOperationId(prefix);
@@ -73,18 +73,19 @@ protected override void SetResponses(OpenApiOperation operation)
}
};
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
protected override void SetSecurity(OpenApiOperation operation)
{
- if (_updateRestriction == null)
+ if (_updateRestriction?.Permissions == null)
{
return;
}
- operation.Security = Context.CreateSecurityRequirements(_updateRestriction.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_updateRestriction.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs
index 76e9232c4..d4f90bc31 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs
@@ -35,28 +35,33 @@ public SingletonGetOperationHandler(OpenApiDocument document) : base(document)
///
public override HttpMethod OperationType => HttpMethod.Get;
- private ReadRestrictionsType _readRestrictions;
+ private ReadRestrictionsType? _readRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- var singletonReadRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.ReadRestrictions);
- _readRestrictions?.MergePropertiesIfNull(singletonReadRestrictions);
- _readRestrictions ??= singletonReadRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _readRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+
+ if (Context is not null && Singleton is not null)
+ {
+ var singletonReadRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.ReadRestrictions);
+ _readRestrictions?.MergePropertiesIfNull(singletonReadRestrictions);
+ _readRestrictions ??= singletonReadRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Descriptions
- string placeHolder = "Get " + Singleton.Name;
+ string placeHolder = "Get " + Singleton?.Name;
operation.Summary = _readRestrictions?.Description ?? placeHolder;
- operation.Description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Singleton);
+ operation.Description = _readRestrictions?.LongDescription ?? Context?.Model.GetDescriptionAnnotation(Singleton);
// OperationId, it should be unique among all operations described in the API.
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && Singleton is not null)
{
string typeName = Singleton.EntityType.Name;
operation.OperationId = Singleton.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(typeName);
@@ -67,16 +72,19 @@ protected override void SetBasicInfo(OpenApiOperation operation)
protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
+
+ if (Singleton is null) return;
// $select
- OpenApiParameter parameter = Context.CreateSelect(Singleton);
+ var parameter = Context?.CreateSelect(Singleton);
+ operation.Parameters ??= [];
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $expand
- parameter = Context.CreateExpand(Singleton);
+ parameter = Context?.CreateExpand(Singleton);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -86,45 +94,49 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- IOpenApiSchema schema = null;
- IDictionary links = null;
-
- if (Context.Settings.EnableDerivedTypesReferencesForResponses)
+ if (Singleton is not null)
{
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(Singleton.EntityType, Context.Model, _document);
- }
+ IOpenApiSchema? schema = null;
+ IDictionary? links = null;
- if (Context.Settings.ShowLinks)
- {
- links = Context.CreateLinks(entityType: Singleton.EntityType, entityName: Singleton.Name,
- entityKind: Singleton.ContainerElementKind.ToString(), path: Path, parameters: PathParameters);
- }
+ if (Context is {Settings.EnableDerivedTypesReferencesForResponses: true})
+ {
+ schema = EdmModelHelper.GetDerivedTypesReferenceSchema(Singleton.EntityType, Context.Model, _document);
+ }
+
+ if (Context is {Settings.ShowLinks: true} && Path is not null)
+ {
+ links = Context.CreateLinks(entityType: Singleton.EntityType, entityName: Singleton.Name,
+ entityKind: Singleton.ContainerElementKind.ToString(), path: Path, parameters: PathParameters);
+ }
- schema ??= new OpenApiSchemaReference(Singleton.EntityType.FullName(), _document);
+ schema ??= new OpenApiSchemaReference(Singleton.EntityType.FullName(), _document);
- operation.Responses = new OpenApiResponses
- {
+ operation.Responses = new OpenApiResponses
{
- Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
- new OpenApiResponse
{
- Description = "Retrieved entity",
- Content = new Dictionary
+ Context?.Settings.UseSuccessStatusCodeRange ?? false ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
+ new OpenApiResponse
{
+ Description = "Retrieved entity",
+ Content = new Dictionary
{
- Constants.ApplicationJsonMediaType,
- new OpenApiMediaType
{
- Schema = schema
+ Constants.ApplicationJsonMediaType,
+ new OpenApiMediaType
+ {
+ Schema = schema
+ }
}
- }
- },
- Links = links
+ },
+ Links = links
+ }
}
- }
- };
+ };
+ }
- operation.AddErrorResponses(Context.Settings, _document, false);
+ if (Context is not null)
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -137,7 +149,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs
index 7e8baa6b0..e49713ccf 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs
@@ -5,6 +5,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
@@ -30,7 +31,7 @@ protected SingletonOperationHandler(OpenApiDocument document):base(document)
///
/// Gets the .
///
- protected IEdmSingleton Singleton { get; private set; }
+ protected IEdmSingleton? Singleton { get; private set; }
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -38,9 +39,8 @@ protected override void Initialize(ODataContext context, ODataPath path)
// Base Initialize should be called at top of this method.
base.Initialize(context, path);
- ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
-
- Singleton = navigationSourceSegment.NavigationSource as IEdmSingleton;
+ if (path.FirstSegment is ODataNavigationSourceSegment {NavigationSource: IEdmSingleton source})
+ Singleton = source;
}
///
@@ -48,9 +48,9 @@ protected override void SetTags(OpenApiOperation operation)
{
// In this SDK, we use "[Singleton Name].[Singleton Entity Type Name]
// For example: "Me.User"
- var tagName = Singleton.Name + "." + Singleton.EntityType.Name;
+ var tagName = Singleton?.Name + "." + Singleton?.EntityType.Name;
- Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ Context?.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
{
Name = tagName
});
@@ -64,6 +64,7 @@ protected override void SetTags(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
+ operation.Extensions ??= new Dictionary();
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("operation"));
base.SetExtensions(operation);
@@ -72,10 +73,10 @@ protected override void SetExtensions(OpenApiOperation operation)
///
protected override void SetExternalDocs(OpenApiOperation operation)
{
- if (Context.Settings.ShowExternalDocs)
+ if (Context is {Settings.ShowExternalDocs: true} && CustomLinkRel is not null)
{
- var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(Singleton, CustomLinkRel);
+ var externalDocs = (string.IsNullOrEmpty(TargetPath) ? null : Context.Model.GetLinkRecord(TargetPath, CustomLinkRel)) ??
+ (Singleton is null ? null : Context.Model.GetLinkRecord(Singleton, CustomLinkRel));
if (externalDocs != null)
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs
index 4342f8f64..cd4f56dea 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs
@@ -35,28 +35,33 @@ public SingletonPatchOperationHandler(OpenApiDocument document) : base(document)
///
public override HttpMethod OperationType => HttpMethod.Patch;
- private UpdateRestrictionsType _updateRestrictions;
+ private UpdateRestrictionsType? _updateRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
- var singletonUpdateRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.UpdateRestrictions);
- _updateRestrictions?.MergePropertiesIfNull(singletonUpdateRestrictions);
- _updateRestrictions ??= singletonUpdateRestrictions;
+ if (!string.IsNullOrEmpty(TargetPath))
+ _updateRestrictions = Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+
+ if (Context is not null && Singleton is not null)
+ {
+ var singletonUpdateRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.UpdateRestrictions);
+ _updateRestrictions?.MergePropertiesIfNull(singletonUpdateRestrictions);
+ _updateRestrictions ??= singletonUpdateRestrictions;
+ }
}
///
protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary and Descriptions
- string placeHolder = "Update " + Singleton.Name;
+ string placeHolder = "Update " + Singleton?.Name;
operation.Summary = _updateRestrictions?.Description ?? placeHolder;
operation.Description = _updateRestrictions?.LongDescription;
// OperationId
- if (Context.Settings.EnableOperationId)
+ if (Context is {Settings.EnableOperationId: true} && Singleton is not null)
{
string typeName = Singleton.EntityType.Name;
operation.OperationId = Singleton.Name + "." + typeName + ".Update" + Utils.UpperFirstChar(typeName);
@@ -87,7 +92,8 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
+ if (Context is not null && GetOpenApiSchema() is {} schema)
+ operation.AddErrorResponses(Context.Settings, _document, true, schema);
base.SetResponses(operation);
}
@@ -99,7 +105,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
+ operation.Security = Context?.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
}
///
@@ -121,9 +127,10 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
}
}
- private IOpenApiSchema GetOpenApiSchema()
+ private IOpenApiSchema? GetOpenApiSchema()
{
- return Context.Settings.EnableDerivedTypesReferencesForRequestBody ?
+ if (Singleton is null) return null;
+ return Context is {Settings.EnableDerivedTypesReferencesForRequestBody: true} ?
EdmModelHelper.GetDerivedTypesReferenceSchema(Singleton.EntityType, Context.Model, _document) :
new OpenApiSchemaReference(Singleton.EntityType.FullName(), _document);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs
index f027d2f14..c83d881ef 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs
@@ -3,8 +3,10 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System.Collections.Generic;
using System.Net.Http;
using Microsoft.OData.Edm;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
@@ -28,7 +30,7 @@ public ComplexPropertyItemHandler(OpenApiDocument document) : base(document)
///
/// Gets the complex property
///
- protected IEdmStructuralProperty ComplexProperty { get; private set; }
+ protected IEdmStructuralProperty? ComplexProperty { get; private set; }
///
protected override void SetOperations(OpenApiPathItem item)
@@ -40,13 +42,16 @@ protected override void SetOperations(OpenApiPathItem item)
public void AddReadOperation(OpenApiPathItem item)
{
- ReadRestrictionsType readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- ReadRestrictionsType complexTypeReadRestrictions = Context.Model.GetRecord(ComplexProperty, CapabilitiesConstants.ReadRestrictions);
- readRestrictions?.MergePropertiesIfNull(complexTypeReadRestrictions);
- readRestrictions ??= complexTypeReadRestrictions;
+ var readRestrictions = string.IsNullOrEmpty(TargetPath) ? null : Context?.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (ComplexProperty is not null)
+ {
+ var complexTypeReadRestrictions = Context?.Model.GetRecord(ComplexProperty, CapabilitiesConstants.ReadRestrictions);
+ readRestrictions?.MergePropertiesIfNull(complexTypeReadRestrictions);
+ readRestrictions ??= complexTypeReadRestrictions;
+ }
bool isReadable = readRestrictions?.Readable ?? false;
- if ((Context.Settings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths && isReadable) ||
- !Context.Settings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths)
+ if (Context is not null && ((Context.Settings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths && isReadable) ||
+ !Context.Settings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths))
{
AddOperation(item, HttpMethod.Get);
}
@@ -54,15 +59,18 @@ public void AddReadOperation(OpenApiPathItem item)
public void AddInsertOperation(OpenApiPathItem item)
{
- if (Path.LastSegment is ODataComplexPropertySegment segment && segment.Property.Type.IsCollection())
+ if (Path?.LastSegment is ODataComplexPropertySegment segment && segment.Property.Type.IsCollection())
{
- InsertRestrictionsType insertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
- InsertRestrictionsType entityInsertRestrictions = Context.Model.GetRecord