Repository: asyncapi/modelina (ts)

Issue:
Java generator should take additionalItems into consideration
#### Reason/Context
Even though we interpret additionalItems (#224) we do not take it into consideration when rendering the Java types for arrays. 

See https://github.com/asyncapi/modelina/issues/224#issuecomment-863200247 for further details on how it should be rendered.


Pull request:
feat: render more accurate array type for Java output
**Description**
This PR renders array type more closely to the underlying structure.

If tuples are encountered the tuple models are combined to ensure that the following CommonModel tuples:
```
items: [
  {
    type: 'string'
  },
  {
    type: 'string'
  }
]
```
are rendered as `String[]` and not `Object[]`.

Furthermore `additionalItems` are taken into account when rendering tuple type to ensure that the appropriate array type is rendered.

**Related issue(s)**
fixes #261 

Patch:
diff --git a/src/generators/java/JavaRenderer.ts b/src/generators/java/JavaRenderer.ts
index 01e67452..b5c63249 100644
--- a/src/generators/java/JavaRenderer.ts
+++ b/src/generators/java/JavaRenderer.ts
@@ -69,7 +69,18 @@ export abstract class JavaRenderer extends AbstractRenderer<JavaOptions> {
     case 'binary':
       return 'byte[]';
     case 'array': {
-      const newType = model?.items ? this.renderType(model.items) : 'Object';
+      let arrayItemModel = model.items;
+      //Since Java dont support tuples, lets make sure that we combine the tuple types to find the appropriate array type 
+      if (Array.isArray(model.items)) {
+        arrayItemModel = model.items.reduce((prevModel, currentModel) => {
+          return CommonModel.mergeCommonModels(CommonModel.toCommonModel(prevModel), CommonModel.toCommonModel(currentModel), {});
+        });
+        //If tuples and additionalItems make sure to find the appropriate type by merging all the tuples and additionalItems model together to find the combined type.
+        if (model.additionalItems !== undefined) {
+          arrayItemModel = CommonModel.mergeCommonModels(arrayItemModel, model.additionalItems, {});
+        }
+      }
+      const newType = arrayItemModel ? this.renderType(arrayItemModel) : 'Object';
       return `${newType}[]`;
     }
     default:
diff --git a/src/generators/java/renderers/ClassRenderer.ts b/src/generators/java/renderers/ClassRenderer.ts
index 35cb78ca..3f52a095 100644
--- a/src/generators/java/renderers/ClassRenderer.ts
+++ b/src/generators/java/renderers/ClassRenderer.ts
@@ -111,5 +111,5 @@ export const JAVA_DEFAULT_CLASS_PRESET: ClassPreset<ClassRenderer> = {
       setterType = `Map<String, ${setterType}>`;
     }
     return `public void set${setterName}(${setterType} ${propertyName}) { this.${propertyName} = ${propertyName}; }`;
-  },
+  }
 };


Test patch:
diff --git a/test/generators/java/JavaRenderer.spec.ts b/test/generators/java/JavaRenderer.spec.ts
index 932e445b..bd399cd1 100644
--- a/test/generators/java/JavaRenderer.spec.ts
+++ b/test/generators/java/JavaRenderer.spec.ts
@@ -38,6 +38,58 @@ describe('JavaRenderer', () => {
     test('Should be able to return byte array', () => {
       expect(renderer.toJavaType('binary', new CommonModel())).toEqual('byte[]');
     });
+    test('Should render matching tuple types as is', () => {
+      const model = CommonModel.toCommonModel({
+        items: [
+          {
+            type: 'string'
+          },
+          {
+            type: 'string'
+          }
+        ]
+      });
+      expect(renderer.toJavaType('array', model)).toEqual('String[]');
+    });
+    test('Should render mismatching tuple types as Object', () => {
+      const model = CommonModel.toCommonModel({ 
+        items: [
+          {
+            type: 'string'
+          },
+          {
+            type: 'number'
+          }
+        ]
+      });
+      expect(renderer.toJavaType('array', model)).toEqual('Object[]');
+    });
+    test('Should render matching tuple and additionalItem types', () => {
+      const model = CommonModel.toCommonModel({
+        items: [
+          {
+            type: 'string'
+          }
+        ],
+        additionalItems: {
+          type: 'string'
+        }
+      });
+      expect(renderer.toJavaType('array', model)).toEqual('String[]');
+    });
+    test('Should render Object for tuple and additionalItem type mismatch', () => {
+      const model = CommonModel.toCommonModel({
+        items: [
+          {
+            type: 'string'
+          }
+        ],
+        additionalItems: {
+          type: 'number'
+        }
+      });
+      expect(renderer.toJavaType('array', model)).toEqual('Object[]');
+    });
   });
 
   describe('toClassType()', () => {