diff --git a/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractCreateMethodsStage.java b/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractCreateMethodsStage.java index f673a89..da3b968 100644 --- a/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractCreateMethodsStage.java +++ b/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractCreateMethodsStage.java @@ -49,6 +49,7 @@ protected void createPropertyMethods(JavaSource javaEntity, PropertyModelWith createAddMethod(javaEntity, collectionPropertyWithOrigin); createClearMethod(javaEntity, collectionPropertyWithOrigin); createRemoveMethod(javaEntity, collectionPropertyWithOrigin); + createInsertMethod(javaEntity, collectionPropertyWithOrigin); } else if (isPrimitive(property) || isPrimitiveList(property) || isPrimitiveMap(property)) { createGetter(javaEntity, propertyWithOrigin); createSetter(javaEntity, propertyWithOrigin); @@ -62,6 +63,7 @@ protected void createPropertyMethods(JavaSource javaEntity, PropertyModelWith createAddMethod(javaEntity, propertyWithOrigin); createClearMethod(javaEntity, propertyWithOrigin); createRemoveMethod(javaEntity, propertyWithOrigin); + createInsertMethod(javaEntity, propertyWithOrigin); } else if (isUnion(property)) { createGetter(javaEntity, propertyWithOrigin); createSetter(javaEntity, propertyWithOrigin); @@ -171,7 +173,7 @@ protected void createFactoryMethod(JavaSource javaEntity, PropertyType proper /** * Creates an "add" method for the given property. The type of the property must be a - * list of entities. The add method would accept a single entity and add it to the list. + * collection of entities. The add method will accept a single entity and add it to the collection. * @param javaEntity * @param propertyWithOrigin */ @@ -219,7 +221,7 @@ protected void createAddMethod(JavaSource javaEntity, PropertyModelWithOrigin /** * Creates a "clear" method for the given property. The type of the property must be a - * list of entities. The clear method will remove all items from the list. + * collection of entities. The clear method will remove all items from the collection. * @param javaEntity * @param propertyWithOrigin */ @@ -237,8 +239,8 @@ protected void createClearMethod(JavaSource javaEntity, PropertyModelWithOrig /** * Creates a "remove" method for the given property. The type of the property must be a - * list of entities. The remove method will remove one item from the list. - * @param entity + * collection of entities. The remove method will remove one item from the collection. + * @param javaEntity * @param propertyWithOrigin */ protected void createRemoveMethod(JavaSource javaEntity, PropertyModelWithOrigin propertyWithOrigin) { @@ -266,6 +268,56 @@ protected void createRemoveMethod(JavaSource javaEntity, PropertyModelWithOri } abstract protected void createRemoveMethodBody(PropertyModel property, MethodSource method); + /** + * Creates an "insert" method for the given property. The type of the property must be a + * collection of entities. The insert method will add one item to the collection at + * a specific index (if possible). + * @param javaEntity + * @param propertyWithOrigin + */ + protected void createInsertMethod(JavaSource javaEntity, PropertyModelWithOrigin propertyWithOrigin) { + PropertyModel property = propertyWithOrigin.getProperty(); + + String _package = propertyWithOrigin.getOrigin().getNamespace().fullName(); + PropertyType type = property.getType().getNested().iterator().next(); + String methodName = insertMethodName(singularize(property.getName())); + MethodSource method; + + if (type.isEntityType()) { + JavaInterfaceSource entityType = resolveJavaEntityType(_package, type); + if (entityType == null) { + error("Could not resolve entity type: " + _package + "::" + type); + return; + } + + javaEntity.addImport(entityType); + + method = ((MethodHolderSource) javaEntity).addMethod().setPublic().setName(methodName).setReturnTypeVoid(); + addAnnotations(method); + if (property.getType().isMap()) { + method.addParameter("String", "name"); + } + method.addParameter(entityType.getName(), "value"); + } else if (type.isPrimitiveType()) { + Class primitiveType = primitiveTypeToClass(type); + javaEntity.addImport(primitiveType); + + method = ((MethodHolderSource) javaEntity).addMethod().setPublic().setName(methodName).setReturnTypeVoid(); + addAnnotations(method); + if (property.getType().isMap()) { + method.addParameter("String", "name"); + } + method.addParameter(primitiveType.getSimpleName(), "value"); + } else { + warn("Type not supported for 'add' method: " + methodName + " with type: " + property.getType()); + return; + } + method.addParameter("int", "atIndex"); + + createInsertMethodBody(javaEntity, property, method); + } + abstract protected void createInsertMethodBody(JavaSource javaEntity, PropertyModel property, MethodSource method); + /** * Create factory methods for any entity types in the union. If the union is, for example, "boolean|string" * then this will do nothing. But if the union is "Widget|string" then a factory method for Widgets will diff --git a/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractJavaStage.java b/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractJavaStage.java index 076364b..227df8a 100644 --- a/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractJavaStage.java +++ b/generator/src/main/java/io/apicurio/umg/pipe/java/AbstractJavaStage.java @@ -177,6 +177,10 @@ protected String getRootNodeEntityClassFQN() { return getState().getConfig().getRootNamespace() + ".RootNodeImpl"; } + protected String getDataModelUtilFQCN() { + return getState().getConfig().getRootNamespace() + ".util.DataModelUtil"; + } + protected String getParentPropertyTypeEnumFQN() { return getState().getConfig().getRootNamespace() + ".ParentPropertyType"; } @@ -233,6 +237,18 @@ protected String addMethodName(String name) { return "add" + StringUtils.capitalize(name); } + protected String insertMethodName(EntityModel entityModel) { + return insertMethodName(entityModel.getName()); + } + + protected String insertMethodName(PropertyModel propertyModel) { + return insertMethodName(propertyModel.getName()); + } + + protected String insertMethodName(String name) { + return "insert" + StringUtils.capitalize(name); + } + protected String clearMethodName(EntityModel entityModel) { return clearMethodName(entityModel.getName()); } diff --git a/generator/src/main/java/io/apicurio/umg/pipe/java/CreateImplMethodsStage.java b/generator/src/main/java/io/apicurio/umg/pipe/java/CreateImplMethodsStage.java index 67f86db..cef9187 100644 --- a/generator/src/main/java/io/apicurio/umg/pipe/java/CreateImplMethodsStage.java +++ b/generator/src/main/java/io/apicurio/umg/pipe/java/CreateImplMethodsStage.java @@ -151,6 +151,34 @@ protected void createMappedNodeMethods(JavaSource javaEntity, PropertyModelWi method.setBody(body.toString()); } + // void insertItem(String name, T item, int atIndex) + { + MethodSource method = ((MethodHolderSource) javaEntity).addMethod().setName("insertItem").setPublic().setReturnTypeVoid(); + method.addAnnotation(Override.class); + method.addParameter("String", "name"); + method.addParameter(mappedNodeType, "item"); + method.addParameter("int", "atIndex"); + + JavaClassSource dataModelUtilSource = getState().getJavaIndex().lookupClass(getDataModelUtilFQCN()); + javaEntity.addImport(dataModelUtilSource); + + BodyBuilder body = new BodyBuilder(); + body.append("this._items = DataModelUtil.insertMapEntry(this._items, name, item, atIndex);"); + if (isEntity(property)) { + JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN()); + javaEntity.addImport(parentPropertyTypeSource); + JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN()); + javaEntity.addImport(nodeImplSource); + + body.append("if (item != null) {"); + body.append(" ((NodeImpl) item)._setParentPropertyName(null);"); + body.append(" ((NodeImpl) item)._setParentPropertyType(ParentPropertyType.map);"); + body.append(" ((NodeImpl) item)._setMapPropertyName(name);"); + body.append("}"); + } + method.setBody(body.toString()); + } + // T removeItem(String name) { MethodSource method = ((MethodHolderSource) javaEntity).addMethod().setName("removeItem").setPublic(); @@ -333,6 +361,69 @@ protected void createRemoveMethodBody(PropertyModel property, MethodSource me method.setBody(body.toString()); } + @Override + protected void createInsertMethodBody(JavaSource javaEntity, PropertyModel property, MethodSource method) { + PropertyType type = property.getType().getNested().iterator().next(); + String fieldName = getFieldName(property); + String propertyName = property.getName(); + + BodyBuilder body = new BodyBuilder(); + body.addContext("fieldName", fieldName); + body.addContext("propertyName", propertyName); + + if (type.isEntityType() || type.isPrimitiveType()) { + if (property.getType().isMap()) { + JavaClassSource dataModelUtilSource = getState().getJavaIndex().lookupClass(getDataModelUtilFQCN()); + javaEntity.addImport(dataModelUtilSource); + javaEntity.addImport(LinkedHashMap.class); + + body.append("if (this.${fieldName} == null) {"); + body.append(" this.${fieldName} = new LinkedHashMap<>();"); + body.append(" this.${fieldName}.put(name, value);"); + body.append("} else {"); + body.append(" this.${fieldName} = DataModelUtil.insertMapEntry(this.${fieldName}, name, value, atIndex);"); + body.append("}"); + + if (type.isEntityType()) { + JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN()); + javaEntity.addImport(parentPropertyTypeSource); + JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN()); + javaEntity.addImport(nodeImplSource); + + body.append("if (value != null) {"); + body.append(" ((NodeImpl) value)._setParentPropertyName(\"${propertyName}\");"); + body.append(" ((NodeImpl) value)._setParentPropertyType(ParentPropertyType.map);"); + body.append(" ((NodeImpl) value)._setMapPropertyName(name);"); + body.append("}"); + } + } else { + JavaClassSource dataModelUtilSource = getState().getJavaIndex().lookupClass(getDataModelUtilFQCN()); + javaEntity.addImport(dataModelUtilSource); + javaEntity.addImport(ArrayList.class); + + body.append("if (this.${fieldName} == null) {"); + body.append(" this.${fieldName} = new ArrayList<>();"); + body.append(" this.${fieldName}.add(value);"); + body.append("} else {"); + body.append(" this.${fieldName} = DataModelUtil.insertListEntry(this.${fieldName}, value, atIndex);"); + body.append("}"); + if (type.isEntityType()) { + JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN()); + javaEntity.addImport(parentPropertyTypeSource); + JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN()); + javaEntity.addImport(nodeImplSource); + + body.append("if (value != null) {"); + body.append(" ((NodeImpl) value)._setParentPropertyName(\"${propertyName}\");"); + body.append(" ((NodeImpl) value)._setParentPropertyType(ParentPropertyType.array);"); + body.append("}"); + } + } + } + + method.setBody(body.toString()); + } + @Override protected void addAnnotations(MethodSource method) { method.addAnnotation(Override.class); diff --git a/generator/src/main/java/io/apicurio/umg/pipe/java/CreateInterfaceMethodsStage.java b/generator/src/main/java/io/apicurio/umg/pipe/java/CreateInterfaceMethodsStage.java index 9663d44..0da3e70 100644 --- a/generator/src/main/java/io/apicurio/umg/pipe/java/CreateInterfaceMethodsStage.java +++ b/generator/src/main/java/io/apicurio/umg/pipe/java/CreateInterfaceMethodsStage.java @@ -131,4 +131,7 @@ protected void createClearMethodBody(PropertyModel property, MethodSource met protected void createRemoveMethodBody(PropertyModel property, MethodSource method) { } + @Override + protected void createInsertMethodBody(JavaSource javaEntity, PropertyModel property, MethodSource method) { + } } diff --git a/generator/src/main/java/io/apicurio/umg/pipe/java/LoadBaseClassesStage.java b/generator/src/main/java/io/apicurio/umg/pipe/java/LoadBaseClassesStage.java index 7ddaf56..f6b79cc 100644 --- a/generator/src/main/java/io/apicurio/umg/pipe/java/LoadBaseClassesStage.java +++ b/generator/src/main/java/io/apicurio/umg/pipe/java/LoadBaseClassesStage.java @@ -30,6 +30,7 @@ protected void doProcess() { loadBaseClasses( "io.apicurio.umg.base.NodeImpl", "io.apicurio.umg.base.RootNodeImpl", + "io.apicurio.umg.base.util.DataModelUtil", "io.apicurio.umg.base.util.JsonUtil", "io.apicurio.umg.base.util.ReaderUtil", "io.apicurio.umg.base.util.WriterUtil", diff --git a/generator/src/main/resources/base/io/apicurio/umg/base/MappedNode.java b/generator/src/main/resources/base/io/apicurio/umg/base/MappedNode.java index 414a69c..4733b3d 100644 --- a/generator/src/main/resources/base/io/apicurio/umg/base/MappedNode.java +++ b/generator/src/main/resources/base/io/apicurio/umg/base/MappedNode.java @@ -29,6 +29,15 @@ public interface MappedNode { */ public void addItem(String name, T item); + /** + * Inserts a child item. + * + * @param name + * @param item + * @param atIndex + */ + public void insertItem(String name, T item, int atIndex); + /** * Removes a child item by name and returns the deleted child or undefined if there wasn't one. * diff --git a/generator/src/main/resources/base/io/apicurio/umg/base/util/DataModelUtil.java b/generator/src/main/resources/base/io/apicurio/umg/base/util/DataModelUtil.java new file mode 100644 index 0000000..98b5893 --- /dev/null +++ b/generator/src/main/resources/base/io/apicurio/umg/base/util/DataModelUtil.java @@ -0,0 +1,46 @@ +package io.apicurio.umg.base.util; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class DataModelUtil { + + public static Map insertMapEntry(Map map, String key, V value, int atIndex) { + // If the new key is present, then return without modification. + if (map.containsKey(key)) { + return map; + } + // If the map isn't an LHM then ordering can't be maintained anyway + // If the atIndex is null then we're trying to undo a command that was persisted prior to this functionality being added + // If the atIndex is >= the map size it has to go at the end anyway + if (!(map instanceof LinkedHashMap) || atIndex >= map.size()){ + map.put(key, value); + return map; + } + + final LinkedHashMap newMap = new LinkedHashMap<>(); + // In order to maintain ordering of the elements when replacing a key in a LinkedHashMap, + // create a new instance and populate it in insertion order + int index = 0; + for (Map.Entry entry : map.entrySet()) { + if (index++ == atIndex) { + newMap.put(key, value); + } + newMap.put(entry.getKey(), entry.getValue()); + } + return newMap; + } + + public static List insertListEntry(List list, V value, int atIndex) { + if (atIndex >= list.size()) { + list.add(value); + } else if (atIndex < 0) { + list.add(0, value); + } else { + list.add(atIndex, value); + } + return list; + } + +} diff --git a/generator/src/test/java/io/apicurio/umg/GeneratorTest.java b/generator/src/test/java/io/apicurio/umg/GeneratorTest.java new file mode 100644 index 0000000..5d2722d --- /dev/null +++ b/generator/src/test/java/io/apicurio/umg/GeneratorTest.java @@ -0,0 +1,50 @@ +package io.apicurio.umg; + +import io.apicurio.umg.io.SpecificationLoader; +import io.apicurio.umg.models.spec.SpecificationModel; +import org.apache.commons.io.FileUtils; +import org.junit.Test; + +import java.io.File; +import java.nio.file.Files; +import java.util.List; + +public class GeneratorTest { + + @Test + public void testGenerator() throws Exception { + File outputDir; + + String outputDirPath = System.getenv("GENERATE_TEST_OUTPUT_DIR"); + if (outputDirPath != null) { + outputDir = new File(outputDirPath); + outputDir.mkdirs(); + } else { + outputDir = Files.createTempDirectory(GeneratorTest.class.getSimpleName()).toFile(); + } + + File umgTestOutputDir = Files.createTempDirectory(GeneratorTest.class.getSimpleName() + "-test").toFile(); + UnifiedModelGeneratorConfig config = UnifiedModelGeneratorConfig.builder() + .outputDirectory(outputDir) + .testOutputDirectory(umgTestOutputDir) + .generateTestFixtures(false) + .rootNamespace("io.apicurio.umg.test").build(); + // Load the specs + List specs = List.of( + SpecificationLoader.loadSpec(GeneratorTest.class.getResource("openapi.yaml")) + ); + // Create a unified model generator + UnifiedModelGenerator generator = new UnifiedModelGenerator(config, specs); + // Generate the source code into the target output directory. + try { + generator.generate(); + } finally { + if (outputDirPath == null) { + FileUtils.deleteDirectory(outputDir); + FileUtils.deleteDirectory(umgTestOutputDir); + } + } + + } + +} \ No newline at end of file diff --git a/generator/src/test/resources/io/apicurio/umg/openapi-3.0.yaml b/generator/src/test/resources/io/apicurio/umg/openapi-3.0.yaml new file mode 100644 index 0000000..2ad4d84 --- /dev/null +++ b/generator/src/test/resources/io/apicurio/umg/openapi-3.0.yaml @@ -0,0 +1,626 @@ +name: OpenAPI 3.0 +version: 3.0 +versions: + - version: 3.0.0 + url: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md + - version: 3.0.1 + url: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md + - version: 3.0.2 + url: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md + - version: 3.0.3 + url: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md +prefix: OpenApi30 +namespace: io.apicurio.umg.test.v30 + +traits: + - name: Extensible + properties: + - name: '/^x-.+$/' + type: any + collection: extensions + - name: Referenceable + properties: + - name: '$ref' + type: string + +entities: + - name: Document + root: true + traits: + - Extensible + properties: + - name: openapi + type: string + - name: info + type: Info + - name: servers + type: '[Server]' + - name: paths + type: Paths + - name: components + type: Components + - name: security + type: '[SecurityRequirement]' + - name: tags + type: '[Tag]' + - name: externalDocs + type: ExternalDocumentation + propertyOrder: + - $this + - $Extensible + + - name: Info + traits: + - Extensible + properties: + - name: title + type: string + - name: description + type: string + - name: termsOfService + type: string + - name: contact + type: Contact + - name: license + type: License + - name: version + type: string + propertyOrder: + - $this + - $Extensible + + - name: Contact + traits: + - Extensible + properties: + - name: name + type: string + - name: url + type: string + - name: email + type: string + propertyOrder: + - $this + - $Extensible + + - name: License + traits: + - Extensible + properties: + - name: name + type: string + - name: url + type: string + propertyOrder: + - $this + - $Extensible + + - name: Server + traits: + - Extensible + properties: + - name: url + type: string + - name: description + type: string + - name: variables + type: '{ServerVariable}' + propertyOrder: + - $this + - $Extensible + + - name: ServerVariable + traits: + - Extensible + properties: + - name: enum + type: '[string]' + - name: default + type: string + - name: description + type: string + propertyOrder: + - $this + - $Extensible + + - name: Components + traits: + - Extensible + properties: + - name: schemas + type: '{Schema}' + - name: responses + type: '{Response}' + - name: parameters + type: '{Parameter}' + - name: examples + type: '{Example}' + - name: requestBodies + type: '{RequestBody}' + - name: headers + type: '{Header}' + - name: securitySchemes + type: '{SecurityScheme}' + - name: links + type: '{Link}' + - name: callbacks + type: '{Callback}' + propertyOrder: + - $this + - $Extensible + + - name: Paths + traits: + - Extensible + properties: + - name: '*' + type: PathItem + propertyOrder: + - $Extensible + - $this + + - name: PathItem + traits: + - Extensible + - Referenceable + properties: + - name: summary + type: string + - name: description + type: string + - name: get + type: Operation + - name: put + type: Operation + - name: post + type: Operation + - name: delete + type: Operation + - name: options + type: Operation + - name: head + type: Operation + - name: patch + type: Operation + - name: trace + type: Operation + - name: servers + type: '[Server]' + - name: parameters + type: '[Parameter]' + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Operation + traits: + - Extensible + properties: + - name: tags + type: '[string]' + - name: summary + type: string + - name: description + type: string + - name: externalDocs + type: ExternalDocumentation + - name: operationId + type: string + - name: parameters + type: '[Parameter]' + - name: requestBody + type: RequestBody + - name: responses + type: Responses + - name: callbacks + type: '{Callback}' + - name: deprecated + type: boolean + - name: security + type: '[SecurityRequirement]' + - name: servers + type: '[Server]' + propertyOrder: + - $this + - $Extensible + + - name: ExternalDocumentation + traits: + - Extensible + properties: + - name: description + type: string + - name: url + type: string + propertyOrder: + - $this + - $Extensible + + - name: Parameter + traits: + - Extensible + - Referenceable + properties: + - name: name + type: string + - name: in + type: string + - name: description + type: string + - name: required + type: boolean + - name: deprecated + type: boolean + - name: allowEmptyValue + type: boolean + - name: style + type: string + - name: explode + type: boolean + - name: allowReserved + type: boolean + - name: schema + type: Schema + - name: example + type: any + - name: examples + type: '{Example}' + - name: content + type: '{MediaType}' + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: RequestBody + traits: + - Extensible + - Referenceable + properties: + - name: description + type: string + - name: content + type: '{MediaType}' + - name: required + type: boolean + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: MediaType + traits: + - Extensible + properties: + - name: schema + type: Schema + - name: example + type: any + - name: examples + type: '{Example}' + - name: encoding + type: '{Encoding}' + propertyOrder: + - $this + - $Extensible + + - name: Encoding + traits: + - Extensible + properties: + - name: contentType + type: string + - name: headers + type: '{Header}' + - name: style + type: string + - name: explode + type: boolean + - name: allowReserved + type: boolean + propertyOrder: + - $this + - $Extensible + + - name: Responses + traits: + - Extensible + - Referenceable + properties: + - name: default + type: Response + - name: '*' + type: Response + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Response + traits: + - Extensible + - Referenceable + properties: + - name: description + type: string + - name: headers + type: '{Header}' + - name: content + type: '{MediaType}' + - name: links + type: '{Link}' + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Callback + traits: + - Extensible + - Referenceable + properties: + - name: '*' + type: PathItem + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Example + traits: + - Extensible + - Referenceable + properties: + - name: summary + type: string + - name: description + type: string + - name: value + type: any + - name: externalValue + type: string + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Link + traits: + - Extensible + - Referenceable + properties: + - name: operationRef + type: string + - name: operationId + type: string + - name: parameters + type: '{any}' # TODO {any|expression} + - name: requestBody + type: any # TODO any|expression + - name: description + type: string + - name: server + type: Server + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Header + traits: + - Extensible + - Referenceable + properties: + - name: description + type: string + - name: required + type: boolean + - name: deprecated + type: boolean + - name: allowEmptyValue + type: boolean + - name: style + type: string + - name: explode + type: boolean + - name: allowReserved + type: boolean + - name: schema + type: Schema + - name: example + type: any + - name: examples + type: '{Example}' + - name: content + type: '{MediaType}' + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Tag + traits: + - Extensible + properties: + - name: name + type: string + - name: description + type: string + - name: externalDocs + type: ExternalDocumentation + propertyOrder: + - $this + - $Extensible + + - name: Schema + traits: + - Extensible + - Referenceable + properties: + - name: format + type: string + - name: title + type: string + - name: description + type: string + - name: default + type: any + - name: multipleOf + type: number + - name: maximum + type: number + - name: exclusiveMaximum + type: boolean + - name: minimum + type: number + - name: exclusiveMinimum + type: boolean + - name: maxLength + type: integer + - name: minLength + type: integer + - name: pattern + type: string + - name: maxItems + type: integer + - name: minItems + type: integer + - name: uniqueItems + type: boolean + - name: maxProperties + type: integer + - name: minProperties + type: integer + - name: required + type: '[string]' + - name: enum + type: '[any]' + - name: type + type: string + - name: items + type: Schema + - name: allOf + type: '[Schema]' + - name: properties + type: '{Schema}' + - name: additionalProperties + type: 'boolean|Schema' + - name: readOnly + type: boolean + - name: xml + type: XML + - name: externalDocs + type: ExternalDocumentation + - name: example + type: any + - name: oneOf + type: '[Schema]' + - name: anyOf + type: '[Schema]' + - name: not + type: Schema + - name: discriminator + type: Discriminator + - name: nullable + type: boolean + - name: writeOnly + type: boolean + - name: deprecated + type: boolean + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: Discriminator + properties: + - name: propertyName + type: string + - name: mapping + type: '{string}' + propertyOrder: + - $this + + - name: XML + traits: + - Extensible + properties: + - name: name + type: string + - name: namespace + type: string + - name: prefix + type: string + - name: attribute + type: boolean + - name: wrapped + type: boolean + propertyOrder: + - $this + - $Extensible + + - name: SecurityScheme + traits: + - Extensible + - Referenceable + properties: + - name: type + type: string + - name: description + type: string + - name: name + type: string + - name: in + type: string + - name: scheme + type: string + - name: bearerFormat + type: string + - name: flows + type: OAuthFlows + - name: openIdConnectUrl + type: string + propertyOrder: + - $Referenceable + - $this + - $Extensible + + - name: OAuthFlows + traits: + - Extensible + properties: + - name: implicit + type: OAuthFlow + - name: password + type: OAuthFlow + - name: clientCredentials + type: OAuthFlow + - name: authorizationCode + type: OAuthFlow + propertyOrder: + - $this + - $Extensible + + - name: OAuthFlow + traits: + - Extensible + properties: + - name: authorizationUrl + type: string + - name: tokenUrl + type: string + - name: refreshUrl + type: string + - name: scopes + type: '{string}' + propertyOrder: + - $this + - $Extensible + + - name: SecurityRequirement + properties: + - name: '*' + type: '[string]' + propertyOrder: + - $this diff --git a/generator/src/test/resources/io/apicurio/umg/openapi.yaml b/generator/src/test/resources/io/apicurio/umg/openapi.yaml new file mode 100755 index 0000000..1a644fe --- /dev/null +++ b/generator/src/test/resources/io/apicurio/umg/openapi.yaml @@ -0,0 +1,7 @@ +name: OpenAPI +url: https://www.openapis.org/ +description: The OpenAPI Specification allows the description of a remote API accessible through HTTP or HTTP-like protocols. +prefix: OpenApi +namespace: io.apicurio.umg.test +versions: + - $ref: ./openapi-3.0.yaml