Skip to content

fix issues in generating product swagger from OAS 3.1 APIs. #13055

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,7 @@ private ConfigParameters() {
public static final String OPEN_API_V3 = "3.0.x";
public static final String OPEN_API = "openapi";
public static final String OAS_V31 = "v31";
public static final String OAS_V30 = "v30";
public static final String OPEN_API_V31_VERSION = "3.1.0";
public static final String OPEN_API_VERSION_REGEX = "3\\.0\\.\\d{1,}";
public static final String SWAGGER_IS_MISSING_MSG = "swagger is missing";
Expand Down Expand Up @@ -1733,6 +1734,11 @@ private ConfigParameters() {
public static final String SWAGGER_RESOURCE_PATH = "resourcePath";
public static final String API_VERSION = "apiVersion";

public static final String OPENAPI_OBJECT_DATA_TYPE = "object";
public static final String OPENAPI_ARRAY_DATA_TYPE = "array";
public static final String OPENAPI_STRING_DATA_TYPE = "string";
public static final String OPENAPIV31_SCHEMA_TYPE_NULLABLE = "null";

//swagger MG related constants
public static final String X_WSO2_AUTH_HEADER = "x-wso2-auth-header";
public static final String X_WSO2_API_KEY_HEADER = "x-wso2-api-key-header";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@
private static final String OPENAPI_RESOURCE_KEY = "paths";
private static final String[] UNSUPPORTED_RESOURCE_BLOCKS = new String[]{"servers"};

static class SwaggerUpdateContext {
public static class SwaggerUpdateContext {
private final Paths paths = new Paths();
private final Set<Scope> aggregatedScopes = new HashSet<>();
private final Map<String, Set<String>> referenceObjectMap = new HashMap<>();
Expand Down Expand Up @@ -725,6 +725,8 @@
} else {
Schema schema = parameter.getSchema();
if (schema != null) {
//Convert the schema format according to the resulting api product openapi version.
convertSchema(schema);

Check warning on line 729 in components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java

View check run for this annotation

Codecov / codecov/patch

components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java#L729

Added line #L729 was not covered by tests
String ref = schema.get$ref();
if (ref != null) {
addToReferenceObjectMap(ref, context);
Expand Down Expand Up @@ -758,9 +760,7 @@
if (content != null) {
for (MediaType mediaType : content.values()) {
Schema schema = mediaType.getSchema();

extractReferenceFromSchema(schema, context);

Map<String, Example> examples = mediaType.getExamples();
if (examples != null) {
for (Map.Entry<String, Example> exampleEntry : examples.entrySet()) {
Expand All @@ -772,93 +772,44 @@
}
}

private static void extractReferenceWithoutSchema(String reference, SwaggerUpdateContext context) {
if (reference != null) {
addToReferenceObjectMap(reference, context);
/**
* Extract all the references (including in nested schemas) of the given schema according to the resulting api
* product openapi version. This method will pick the correct schema processor according to the openapi version
* in the given schema object.
*
* @param schema OpenAPI 3.x Schema object
* @param context SwaggerUpdateContext which holds the reference object map
*/
public static void extractReferenceFromSchema(Schema<?> schema, SwaggerUpdateContext context) {
try {
if (schema == null) return;
SchemaProcessor processor = SchemaProcessorFactory.getProcessor(schema);
processor.extractReferenceFromSchema(schema, context);
} catch (IllegalArgumentException exception) {
log.error("Invalid schema spec version. Skipping extracting references.");

Check warning on line 789 in components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java

View check run for this annotation

Codecov / codecov/patch

components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java#L788-L789

Added lines #L788 - L789 were not covered by tests
}
}

private static void extractReferenceFromSchema(Schema schema, SwaggerUpdateContext context) {
if (schema != null) {
String ref = schema.get$ref();
List<String> references = new ArrayList<String>();
if (ref == null) {
if (schema instanceof ArraySchema) {
ArraySchema arraySchema = (ArraySchema) schema;
Schema itemsSchema = arraySchema.getItems();
// Process $ref items
ref = itemsSchema.get$ref();
if (ref == null) {
// Process items in the form of Composed Schema such as allOf, oneOf, anyOf
extractReferenceFromSchema(itemsSchema, context);
}
} else if (schema instanceof ObjectSchema) {
references = addSchemaOfSchema(schema, context);
} else if (schema instanceof MapSchema) {
Schema additionalPropertiesSchema = (Schema) schema.getAdditionalProperties();
extractReferenceFromSchema(additionalPropertiesSchema, context);
} else if (schema instanceof ComposedSchema) {
if (((ComposedSchema) schema).getAllOf() != null) {
for (Schema sc : ((ComposedSchema) schema).getAllOf()) {
if (OBJECT_DATA_TYPE.equalsIgnoreCase(sc.getType())) {
references.addAll(addSchemaOfSchema(sc, context));
} else {
String schemaRef = sc.get$ref();
if (schemaRef != null) {
references.add(sc.get$ref());
} else {
processSchemaProperties(sc, context);
}
}
}
}
if (((ComposedSchema) schema).getAnyOf() != null) {
for (Schema sc : ((ComposedSchema) schema).getAnyOf()) {
if (OBJECT_DATA_TYPE.equalsIgnoreCase(sc.getType())) {
references.addAll(addSchemaOfSchema(sc, context));
} else {
String schemaRef = sc.get$ref();
if (schemaRef != null) {
references.add(sc.get$ref());
} else {
processSchemaProperties(sc, context);
}
}
}
}
if (((ComposedSchema) schema).getOneOf() != null) {
for (Schema sc : ((ComposedSchema) schema).getOneOf()) {
if (OBJECT_DATA_TYPE.equalsIgnoreCase(sc.getType())) {
references.addAll(addSchemaOfSchema(sc, context));
} else {
String schemaRef = sc.get$ref();
if (schemaRef != null) {
references.add(sc.get$ref());
} else {
processSchemaProperties(sc, context);
}
}
}
}
if (((ComposedSchema) schema).getAllOf() == null &&
((ComposedSchema) schema).getAnyOf() == null &&
((ComposedSchema) schema).getOneOf() == null) {
log.error("Unidentified schema. The schema is not available in the API definition.");
}
}
}

if (ref != null) {
addToReferenceObjectMap(ref, context);
} else if (!references.isEmpty() && references.size() != 0) {
for (String reference : references) {
if (reference != null) {
addToReferenceObjectMap(reference, context);
}
}
}
/**
* Process ArraySchema while recursively traversing through array schema items. Used for both openapi 3.1 and 3.0.
*
* @param schema ArraySchema
* @param context SwaggerUpdateContext
*/
protected static void processArraySchema(Schema<?> schema, SwaggerUpdateContext context) {
convertSchema(schema);
Schema<?> itemsSchema = schema.getItems();
String ref = itemsSchema.get$ref();
if (ref == null) {
extractReferenceFromSchema(itemsSchema, context);
} else {
OASParserUtil.addToReferenceObjectMap(ref, context);
}
}

processSchemaProperties(schema, context);
private static void extractReferenceWithoutSchema(String reference, SwaggerUpdateContext context) {
if (reference != null) {
addToReferenceObjectMap(reference, context);

Check warning on line 812 in components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java

View check run for this annotation

Codecov / codecov/patch

components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java#L812

Added line #L812 was not covered by tests
}
}

Expand All @@ -868,8 +819,9 @@
* @param schema The schema object which contains the properties which needs to be processed.
* @param context The SwaggerUpdateContext object containing the context of the API definition.
*/
private static void processSchemaProperties(Schema schema, SwaggerUpdateContext context) {
protected static void processSchemaProperties(Schema schema, SwaggerUpdateContext context) {
// Process schema properties if present
convertSchema(schema);
Map properties = schema.getProperties();
if (properties != null) {
for (Object propertySchema : properties.values()) {
Expand All @@ -878,44 +830,24 @@
}
}

private static List<String> addSchemaOfSchema(Schema schema, SwaggerUpdateContext context) {
List<String> references = new ArrayList<String>();
ObjectSchema os = (ObjectSchema) schema;
if (os.getProperties() != null) {
for (String propertyName : os.getProperties().keySet()) {
Schema propertySchema = os.getProperties().get(propertyName);

if (propertySchema.get$ref() != null) {
references.add(propertySchema.get$ref());
}

if (propertySchema instanceof ComposedSchema) {
ComposedSchema cs = (ComposedSchema) propertySchema;
if (cs.getAllOf() != null) {
for (Schema sc : cs.getAllOf()) {
references.add(sc.get$ref());
}
} else if (cs.getAnyOf() != null) {
for (Schema sc : cs.getAnyOf()) {
references.add(sc.get$ref());
}
} else if (cs.getOneOf() != null) {
for (Schema sc : cs.getOneOf()) {
references.add(sc.get$ref());
}
} else {
log.error("Unidentified schema. The schema is not available in the API definition.");
}
} else if (propertySchema instanceof ObjectSchema ||
propertySchema instanceof ArraySchema) {
extractReferenceFromSchema(propertySchema, context);
}
}
/**
* Convert the OpenAPI 3.x Schema<T> format accordingly to the current Schema's OpenAPI version and resulting
* API product OpenAPI version. This method picks the correct SchemaProcessor to do the conversion and hand over
* the Schema object for that.
*
* @param schema Schema
*/
protected static void convertSchema(Schema<?> schema) {
if (schema == null) return;
try {
SchemaProcessor processor = SchemaProcessorFactory.getProcessor(schema);
processor.convertSchema(schema);
} catch (IllegalArgumentException exception) {
log.error("Invalid schema spec version. Skipping the conversion of the schema.");

Check warning on line 846 in components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java

View check run for this annotation

Codecov / codecov/patch

components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java#L845-L846

Added lines #L845 - L846 were not covered by tests
}
return references;
}

private static void addToReferenceObjectMap(String ref, SwaggerUpdateContext context) {
protected static void addToReferenceObjectMap(String ref, SwaggerUpdateContext context) {
Map<String, Set<String>> referenceObjectMap = context.getReferenceObjectMapping();
final String category = getComponentCategory(ref);
if (referenceObjectMap.containsKey(category)) {
Expand All @@ -924,12 +856,12 @@
}
}

private static String getRefKey(String ref) {
protected static String getRefKey(String ref) {
String[] split = ref.split("/");
return split[split.length - 1];
}

private static String getComponentCategory(String ref) {
protected static String getComponentCategory(String ref) {
String[] remainder = ref.split(REF_PREFIX);

if (remainder.length == 2) {
Expand Down
Loading
Loading