Repository: swagger-api/swagger-parser
Pull request #1344 (2020-03-31 18:09:16)

flatten inline composedSchema
flatten inline composedSchema


Patch:
diff --git a/modules/swagger-parser-core/src/main/java/io/swagger/v3/parser/core/models/ParseOptions.java b/modules/swagger-parser-core/src/main/java/io/swagger/v3/parser/core/models/ParseOptions.java
index 8de23203..9814dde6 100644
--- a/modules/swagger-parser-core/src/main/java/io/swagger/v3/parser/core/models/ParseOptions.java
+++ b/modules/swagger-parser-core/src/main/java/io/swagger/v3/parser/core/models/ParseOptions.java
@@ -6,6 +6,7 @@ public class ParseOptions {
     private boolean resolveFully;
     private boolean flatten;
     private boolean flattenComposedSchemas;
+    private boolean camelCaseFlattenNaming;
     private boolean skipMatches;
 
     public boolean isResolve() {
@@ -51,4 +52,11 @@ public class ParseOptions {
     public void setFlattenComposedSchemas(boolean flattenComposedSchemas) {
         this.flattenComposedSchemas = flattenComposedSchemas;
     }
+    public boolean isCamelCaseFlattenNaming() {
+        return camelCaseFlattenNaming;
+    }
+
+    public void setCamelCaseFlattenNaming(boolean camelCaseFlattenNaming) {
+        this.camelCaseFlattenNaming = camelCaseFlattenNaming;
+    }
 }
diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java
index e4af7e1a..ebeee304 100644
--- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java
+++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java
@@ -70,7 +70,7 @@ public class OpenAPIV3Parser implements SwaggerParserExtension {
                             result.setOpenAPI(resolver.resolve());
                             new ResolverFully(options.isResolveCombinators()).resolveFully(result.getOpenAPI());
                         } else if (options.isFlatten()) {
-                            InlineModelResolver inlineModelResolver = new InlineModelResolver(options.isFlattenComposedSchemas());
+                            InlineModelResolver inlineModelResolver = new InlineModelResolver(options.isFlattenComposedSchemas(), options.isCamelCaseFlattenNaming());
                             inlineModelResolver.setSkipMatches(options.isSkipMatches());
                             inlineModelResolver.flatten(result.getOpenAPI());
                         }
@@ -207,7 +207,7 @@ public class OpenAPIV3Parser implements SwaggerParserExtension {
                         result.setOpenAPI(new OpenAPIResolver(result.getOpenAPI(), auth, null).resolve());
                         new ResolverFully(options.isResolveCombinators()).resolveFully(result.getOpenAPI());
                     } else if (options.isFlatten()) {
-                        InlineModelResolver inlineModelResolver = new InlineModelResolver(options.isFlattenComposedSchemas());
+                        InlineModelResolver inlineModelResolver = new InlineModelResolver(options.isFlattenComposedSchemas(), options.isCamelCaseFlattenNaming());
                         inlineModelResolver.setSkipMatches(options.isSkipMatches());
                         inlineModelResolver.flatten(result.getOpenAPI());
                     }
diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java
index bd6e6b6d..3f18d9d0 100644
--- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java
+++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java
@@ -33,12 +33,13 @@ public class InlineModelResolver {
     Map<String, String> generatedSignature = new HashMap<>();
 
     private boolean flattenComposedSchemas;
+    private boolean camelCaseFlattenNaming;
 
+    public InlineModelResolver(){this(false,false);}
 
-    public InlineModelResolver(){this(false);}
-
-    public InlineModelResolver(boolean flattenComposedSchemas) {
+    public InlineModelResolver(boolean flattenComposedSchemas, boolean camelCaseFlattenNaming) {
         this.flattenComposedSchemas = flattenComposedSchemas;
+        this.camelCaseFlattenNaming = camelCaseFlattenNaming;
     }
 
     public void flatten(OpenAPI openAPI) {
@@ -53,7 +54,7 @@ public class InlineModelResolver {
 
         // operations
         Map<String, PathItem> paths = openAPI.getPaths();
-        if(openAPI.getComponents()== null){
+        if (openAPI.getComponents()== null){
             openAPI.setComponents(new Components());
         }
         Map<String, Schema> models = openAPI.getComponents().getSchemas();
@@ -71,7 +72,7 @@ public class InlineModelResolver {
                             for(String key: content.keySet()) {
                                 if (content.get(key) != null) {
                                     MediaType mediaType = content.get(key);
-                                    if(mediaType.getSchema() != null) {
+                                    if (mediaType.getSchema() != null) {
                                         Schema model = mediaType.getSchema();
                                         if (model.getProperties() != null && model.getProperties().size() > 0) {
                                             flattenProperties(model.getProperties(), pathname);
@@ -258,17 +259,33 @@ public class InlineModelResolver {
                     }
                 } else if (model instanceof ComposedSchema) {
                     ComposedSchema composedSchema = (ComposedSchema) model;
+                    String inlineModelName = "";
+
                     List<Schema> list = null;
                     if (composedSchema.getAllOf() != null) {
-                      list  = composedSchema.getAllOf();
+                        list  = composedSchema.getAllOf();
+                        inlineModelName = "AllOf";
                     }else if (composedSchema.getAnyOf() != null) {
                         list  = composedSchema.getAnyOf();
+                        inlineModelName = "AnyOf";
                     }else if (composedSchema.getOneOf() != null) {
                         list  = composedSchema.getOneOf();
+                        inlineModelName = "OneOf";
                     }
+
                     for(int i= 0; i<list.size();i++){
-                        if(list.get(i).getProperties()!= null){
-                            flattenProperties(list.get(i).getProperties(), modelName);
+                        if (list.get(i).get$ref() == null){
+                            Schema inline = list.get(i);
+                            if (inline.getProperties()!= null){
+                                flattenProperties(inline.getProperties(), modelName);
+                            }
+                            if (this.flattenComposedSchemas) {
+                                int position = i+1;
+                                inlineModelName = resolveModelName(inline.getTitle(),  modelName + inlineModelName + "_" + position);
+                                list.set(i,new Schema().$ref(inlineModelName));
+                                addGenerated(inlineModelName, inline);
+                                openAPI.getComponents().addSchemas(inlineModelName, inline);
+                            }
                         }
                     }
                 }
@@ -276,6 +293,8 @@ public class InlineModelResolver {
         }
     }
 
+
+
     /**
      * This function fix models that are string (mostly enum). Before this fix, the example
      * would look something like that in the doc: "\"example from def\""
@@ -317,7 +336,18 @@ public class InlineModelResolver {
     public String uniqueName(String key) {
         int count = 0;
         boolean done = false;
-        key = key.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter
+        if (camelCaseFlattenNaming) {
+            String uniqueKey;
+            String concatenated = "";
+            for (int i = 0; i < key.split("-").length; i++) {
+                uniqueKey = key.split("-")[i];
+                uniqueKey = uniqueKey.substring(0, 1).toUpperCase() + uniqueKey.substring(1);
+                concatenated = concatenated.concat(uniqueKey);
+            }
+            key = concatenated.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter
+        }else {
+            key = key.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter
+        }
         // should not be
         // assigned. Also declare
         // the methods parameters
@@ -337,6 +367,7 @@ public class InlineModelResolver {
         return key;
     }
 
+
     public void flattenProperties(Map<String, Schema> properties, String path) {
         if (properties == null) {
             return;
@@ -377,7 +408,7 @@ public class InlineModelResolver {
                             addGenerated(modelName, innerModel);
                             openAPI.getComponents().addSchemas(modelName, innerModel);
                         }
-                    }else if(inner instanceof ComposedSchema && this.flattenComposedSchemas){
+                    }else if (inner instanceof ComposedSchema && this.flattenComposedSchemas){
                         ComposedSchema composedSchema = (ComposedSchema) inner;
                         String modelName = resolveModelName(inner.getTitle(), path + "_" + key);
                         List<Schema> list = null;
@@ -389,7 +420,7 @@ public class InlineModelResolver {
                             list  = composedSchema.getOneOf();
                         }
                         for(int i= 0; i<list.size();i++){
-                            if(list.get(i).getProperties()!= null){
+                            if (list.get(i).getProperties()!= null){
                                 flattenProperties(list.get(i).getProperties(), modelName);
                             }
                         }
@@ -546,7 +577,7 @@ public class InlineModelResolver {
      * @param target target property
      */
     public void copyVendorExtensions(Schema source, Schema target) {
-        if(source.getExtensions() != null) {
+        if (source.getExtensions() != null) {
             Map<String, Object> vendorExtensions = source.getExtensions();
             for (String extName : vendorExtensions.keySet()) {
                 target.addExtension(extName, vendorExtensions.get(extName));
@@ -566,6 +597,5 @@ public class InlineModelResolver {
         return schema instanceof ObjectSchema
                 || "object".equalsIgnoreCase(schema.getType())
                 || (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty());
-
     }
 }


Test patch:
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
index f4ca4e38..c1dee094 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
@@ -66,13 +66,56 @@ public class OpenAPIV3ParserTest {
     protected int serverPort = getDynamicPort();
     protected WireMockServer wireMockServer;
 
+
+    @Test
+    public void testCamelCaseFlattenNamingFalse() {
+        OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        options.setFlatten(true);
+        options.setFlattenComposedSchemas(true);
+        options.setCamelCaseFlattenNaming(false);
+        SwaggerParseResult parseResult = openApiParser.readLocation("FlattenComposedSchemasAtComponents.yaml", null, options);
+        OpenAPI openAPI = parseResult.getOpenAPI();
+        assertNotNull(openAPI);
+        assertEquals(((ComposedSchema)openAPI.getComponents().getSchemas().get("contact-base-model")).getAllOf().get(0).get$ref(),"#/components/schemas/contactbasemodelAllOf_1");
+    }
+
+    @Test
+    public void testIssueFlattenComposedSchemaInlineModel() {
+        OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        options.setFlatten(true);
+        options.setFlattenComposedSchemas(true);
+        options.setCamelCaseFlattenNaming(true);
+        SwaggerParseResult parseResult = openApiParser.readLocation("FlattenComposedSchemasAtComponents.yaml", null, options);
+        OpenAPI openAPI = parseResult.getOpenAPI();
+        assertNotNull(openAPI);
+        assertEquals(((ComposedSchema)openAPI.getComponents().getSchemas().get("contact-base-model")).getAllOf().get(0).get$ref(),"#/components/schemas/ContactBaseModelAllOf_1");
+        assertEquals(((ComposedSchema)openAPI.getComponents().getSchemas().get("Test")).getOneOf().get(1).get$ref(),"#/components/schemas/TestOneOf_2");
+    }
+
+    @Test
+    public void testIssueFlattenComposedSchemaInlineModelFlagFalse() {
+        OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        options.setFlatten(true);
+        options.setFlattenComposedSchemas(false);
+        SwaggerParseResult parseResult = openApiParser.readLocation("FlattenComposedSchemasAtComponents.yaml", null, options);
+        OpenAPI openAPI = parseResult.getOpenAPI();
+        assertNotNull(openAPI);
+        assertNull(((ComposedSchema)openAPI.getComponents().getSchemas().get("contact-base-model")).getAllOf().get(0).get$ref());
+        assertNull(((ComposedSchema)openAPI.getComponents().getSchemas().get("Test")).getOneOf().get(1).get$ref());
+    }
+
     @Test
     public void testIssue1309() {
         OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
         SwaggerParseResult parseResult = openApiParser.readLocation("issue-1309.yaml", null, options);
-
         OpenAPI openAPI = parseResult.getOpenAPI();
         assertNotNull(openAPI);
         assertEquals(parseResult.getMessages().get(0),"attribute components.schemas.customer-not-found.examples is unexpected");
@@ -84,7 +127,6 @@ public class OpenAPIV3ParserTest {
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
         SwaggerParseResult parseResult = openApiParser.readLocation("Issue1316.yaml", null, options);
-
         OpenAPI openAPI = parseResult.getOpenAPI();
         assertNotNull(openAPI);
         assertTrue(parseResult.getMessages().size() == 0);
@@ -96,11 +138,8 @@ public class OpenAPIV3ParserTest {
         OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
-
         SwaggerParseResult parseResult = openApiParser.readLocation("issue-1292/petstore.yml", null, options);
-
         OpenAPI openAPI = parseResult.getOpenAPI();
-
         assertNotNull(openAPI.getPaths().get("/pets").getGet().getResponses().get("200").getContent().get("application/json").getSchema().get$ref(), "#/components/schemas/Pets");
         assertNotNull(openAPI.getPaths().get("/pets").getGet().getResponses().getDefault().getContent().get("application/json").getSchema().get$ref(), "#/components/schemas/Error");
         assertNotNull(openAPI.getComponents().getSchemas().get("Pet"));
@@ -120,7 +159,6 @@ public class OpenAPIV3ParserTest {
         OpenAPI openAPI = parseResult.getOpenAPI();
         assertNotNull(openAPI.getComponents().getSchemas().get("val_Members_val_member"));
         assertNotNull(openAPI.getComponents().getSchemas().get("val_MemberProducts_val_product"));
-
     }
 
     @Test
@@ -135,7 +173,6 @@ public class OpenAPIV3ParserTest {
         OpenAPI openAPI = parseResult.getOpenAPI();
         assertNull(openAPI.getComponents().getSchemas().get("val_Members_val_member"));
         assertNotNull(openAPI.getComponents().getSchemas().get("val_MemberProducts_val_product"));
-
     }
 
     @Test
@@ -252,16 +289,13 @@ public class OpenAPIV3ParserTest {
 
     @Test
     public void testRemoteParameterIssue1094(@Injectable final List<AuthorizationValue> auths) throws Exception{
-
         OpenAPI result = new OpenAPIV3Parser().read("issue-1094/swagger.yaml");
         Assert.assertNotNull(result);
         Assert.assertNotNull(result.getComponents().getSchemas().get("PlmnId"));
-
     }
 
     @Test
     public void testIssue1071() {
-
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
 
@@ -270,15 +304,12 @@ public class OpenAPIV3ParserTest {
         assertNotNull(apispec);
         Schema test = apispec.getPaths().get("/mapschema").getGet().getResponses().get("200").getContent().get("application/json").getSchema();
         assertTrue(test instanceof MapSchema);
-
     }
 
     @Test
     public void testIssue1071True() {
-
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
-
         SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation("issue-1071-true.yaml", null, options);
         OpenAPI apispec = parseResult.getOpenAPI();
         assertNotNull(apispec);
@@ -286,15 +317,12 @@ public class OpenAPIV3ParserTest {
         assertTrue(test instanceof MapSchema);
         assertTrue(test.getAdditionalProperties() instanceof Boolean);
         assertTrue((Boolean)test.getAdditionalProperties());
-
     }
 
     @Test
     public void testIssue1071False() {
-
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
-
         SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation("issue-1071-false.yaml", null, options);
         OpenAPI apispec = parseResult.getOpenAPI();
         assertNotNull(apispec);
@@ -302,25 +330,20 @@ public class OpenAPIV3ParserTest {
         assertTrue(test instanceof ObjectSchema);
         assertTrue(test.getAdditionalProperties() instanceof Boolean);
         assertFalse((Boolean)test.getAdditionalProperties());
-
     }
 
     @Test
     public void testIssue1039() {
-
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
-
         SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation("issue_1039.yaml", null, options);
         OpenAPI apispec = parseResult.getOpenAPI();
         assertNotNull(apispec);
         assertEquals(apispec.getPaths().get("/pets").getGet().getParameters().get(0).getSchema().getType(),"array");
-
     }
 
     @Test
     public void testIssue1015() {
-
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
         options.setResolveCombinators(true);
@@ -329,7 +352,6 @@ public class OpenAPIV3ParserTest {
             parseResult.getMessages().forEach(s -> System.out.println(s));
             fail("Error while loading apispec!");
         }
-
         OpenAPI apispec = parseResult.getOpenAPI();
         assertNotNull(apispec);
     }
@@ -397,7 +419,6 @@ public class OpenAPIV3ParserTest {
         options.setResolve(true);
         options.setFlatten(true);
         final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("issue-837-853-1131/main.yaml", null, options).getOpenAPI();
-
         Assert.assertNotNull(openAPI);
 
         Operation post = openAPI.getPaths().get("/guests").getPost();
@@ -412,7 +433,6 @@ public class OpenAPIV3ParserTest {
         assertNotNull(openAPI.getComponents().getExamples());
         assertNotNull(openAPI.getComponents().getExamples().get("testExample"));
         assertEquals(((LinkedHashMap<String, Object>)openAPI.getComponents().getExamples().get("testExample").getValue()).get("test"),"value");
-
     }
 
     @Test
@@ -420,7 +440,6 @@ public class OpenAPIV3ParserTest {
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
         final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("issue-837-853-1131/main.yaml", null, options).getOpenAPI();
-
         Assert.assertNotNull(openAPI);
 
         Content content = openAPI.getPaths().get("/events").getGet().getResponses().get("200").getContent();
@@ -438,7 +457,6 @@ public class OpenAPIV3ParserTest {
         ParseOptions options = new ParseOptions();
         options.setResolve(true);
         final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("issue-837-853-1131/main.yaml", null, options).getOpenAPI();
-
         Assert.assertNotNull(openAPI);
 
         Content content = openAPI.getPaths().get("/events").getGet().getRequestBody().getContent();
@@ -506,17 +524,14 @@ public class OpenAPIV3ParserTest {
 
         Assert.assertNotNull(openAPI);
         Assert.assertEquals(openAPI.getPaths().get("/").getGet().getResponses().get("200").getContent().get("application/json").getSchema().get$ref(),"#/components/schemas/schema-with-reference");
-
     }
 
     @Test
     public void testIssue719() {
         final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("extensions-responses.yaml", null, new ParseOptions()).getOpenAPI();
-
         Assert.assertNotNull(openAPI);
         Assert.assertNotNull(openAPI.getPaths().getExtensions());
         Assert.assertNotNull(openAPI.getPaths().get("/something").getGet().getResponses().getExtensions());
-
     }
 
     @Test
@@ -557,7 +572,6 @@ public class OpenAPIV3ParserTest {
     @Test
     public void testPattern() {
         final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("testPattern.yaml", null, new ParseOptions()).getOpenAPI();
-
         Schema s = openAPI.getComponents().getSchemas().get("SomeObj");
         Assert.assertEquals(s.getPattern(),"^[A-Z]+$"); //ERROR: got null
     }
@@ -669,7 +683,6 @@ public class OpenAPIV3ParserTest {
                         .withHeader("Content-type", "application/json")
                         .withBody(pathFile
                                 .getBytes(StandardCharsets.UTF_8))));
-
     }
 
     @AfterClass
@@ -1108,7 +1121,6 @@ public class OpenAPIV3ParserTest {
         assertTrue(definitions.containsKey("z"));
         assertEquals( definitions.get("i").get$ref(),"#/components/schemas/k");
         assertEquals( definitions.get("k").getTitle(), "k-definition");
-
     }
 
     @Test
@@ -1355,7 +1367,6 @@ public class OpenAPIV3ParserTest {
 
         assertTrue(stringBodyParameter.getRequired());
 
-
         Schema sbpModel = stringBodyParameter.getContent().get("application/json").getSchema();
 
         assertEquals(sbpModel.getType(), "string");
@@ -1374,7 +1385,6 @@ public class OpenAPIV3ParserTest {
         options.setResolve(true);
         SwaggerParseResult readResult = parser.readLocation("src/test/resources/relative-issue/api.yaml", null, options);
         Assert.assertEquals(readResult.getOpenAPI().getPaths().get("/scans").getGet().getResponses().get("500").getContent().get("application/json").getSchema().get$ref(), "#/components/schemas/ErrorMessage");
-
     }
 
     @Test
@@ -1775,7 +1785,6 @@ public class OpenAPIV3ParserTest {
         assertEquals(schema.getItems().get$ref(),"#/components/schemas/Pet");
         assertNotNull(schema.getMaxItems());
         assertNotNull(schema.getMinItems());
-
     }
 
     @Test
@@ -2267,9 +2276,7 @@ public class OpenAPIV3ParserTest {
         options.setSkipMatches(true);
 
         final OpenAPIV3Parser parserUnderTest = new OpenAPIV3Parser();
-
         final SwaggerParseResult result = parserUnderTest.readLocation(location, null, options);
-
         final OpenAPI openAPI = result.getOpenAPI();
 
         assertNotNull(openAPI);
diff --git a/modules/swagger-parser-v3/src/test/resources/FlattenComposedSchemasAtComponents.yaml b/modules/swagger-parser-v3/src/test/resources/FlattenComposedSchemasAtComponents.yaml
new file mode 100644
index 00000000..a2e87330
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/FlattenComposedSchemasAtComponents.yaml
@@ -0,0 +1,73 @@
+openapi: 3.0.2
+info:
+  title: CC-20272 test - OAS3
+  version: 1.0.0
+paths:
+  /something:
+    get:
+      responses:
+        200:
+          description: ok
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Bar'
+components:
+  schemas:
+    Foo:
+      type: object
+      properties:
+        foo:
+          type: string
+    Bar:
+      type: object
+      properties:
+        foo1:
+          description: An instance of Foo
+          allOf:
+            - $ref: '#/components/schemas/Foo'
+        foo2:
+          $ref: '#/components/schemas/Foo'
+    Test:
+      oneOf:
+        - $ref: "#/components/schemas/Foo"
+        - type: object
+          properties:
+            foo:
+              type: string
+    contact-base-model:
+      allOf:
+        - type: object
+          required:
+            - lastName
+            - email
+          properties:
+            contactId:
+              type: string
+              readOnly: true
+            fullName:
+              type: string
+              readOnly: true
+            firstName:
+              type: string
+            lastName:
+              type: string
+            title:
+              type: string
+            email:
+              type: string
+              format: email
+            passCode:
+              type: string
+              format: password
+            indivId:
+              type: string
+            addresses:
+              type: array
+              items:
+                $ref: '#/components/schemas/address-model'
+            phones:
+              type: array
+              items:
+                $ref: '#/components/schemas/phone-model'
+        - $ref: '#/components/schemas/audit-model'
\ No newline at end of file