Skip to content

Commit

Permalink
fix: when allowInheritance is true, java now renders setters in inter…
Browse files Browse the repository at this point in the history
…faces for enums if const is not set by the classes that implements it
  • Loading branch information
kennethaasan committed Sep 5, 2024
1 parent 1b561f9 commit cc4e368
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 35 deletions.
4 changes: 2 additions & 2 deletions docs/migrations/version-3-to-4.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,6 @@ type info struct {

## Java

### when allowInheritance is true, Modelina now don't render the setter for enums in interfaces because the classes that implement the interface might use a constant value
### When `allowInheritance` is true, Modelina no longer renders the setter for enums in interfaces if the enum is implemented by a class and has a constant value

In Java, when a class implements an interface, it must implement all the methods of that interface. Because of that, Modelina now doesn't render the setter for enums in interfaces when allowInheritance is true because the classes that implement the interface might use a constant value.
In Java, when a class implements an interface, it must implement all the methods of that interface. Therefore, if `allowInheritance` is set to true, Modelina will no longer render the setter for enums in interfaces if the enum is implemented by a class and has a constant value.
22 changes: 22 additions & 0 deletions src/generators/AbstractGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,28 @@ export abstract class AbstractGenerator<
}

for (const { constrainedModel } of constrainedModelsWithDepManager) {
if (constrainedModel.options.extend) {
for (const extend of constrainedModel.options.extend) {
const extendModel = constrainedModelsWithDepManager.find(
(m) => m.constrainedModel.name === extend.name
);

if (!extendModel) {
throw new Error(
`Could not find the model ${extend.name} to extend in the constrained models`
);
}

if (!extendModel.constrainedModel.options.implementedBy) {
extendModel.constrainedModel.options.implementedBy = [];
}

extendModel.constrainedModel.options.implementedBy.push(
constrainedModel
);
}
}

for (const unionConstrainedModel of unionConstrainedModelsWithDepManager) {
if (
unionConstrainedModel.constrainedModel instanceof
Expand Down
36 changes: 32 additions & 4 deletions src/generators/java/renderers/ClassRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,29 @@ export const isDiscriminatorOrDictionary = (
property.unconstrainedPropertyName ||
property.property instanceof ConstrainedDictionaryModel;

const isEnumImplementedByConstValue = (
model: ConstrainedObjectModel,
property: ConstrainedObjectPropertyModel
): boolean => {
if (!isEnum(property)) {
return false;
}

if (!model.options.implementedBy) {
return false;
}

// if the implementedBy property exist in the model options, check if the property exists in the implementedBy model and check if the property is set with a const value
return model.options.implementedBy.some((implementedBy) => {
return (
implementedBy instanceof ConstrainedObjectModel &&
implementedBy.properties[property.propertyName] &&
implementedBy.properties[property.propertyName].property.options.const
?.value
);
});
};

export const JAVA_DEFAULT_CLASS_PRESET: ClassPresetType<JavaOptions> = {
self({ renderer }) {
return renderer.defaultSelf();
Expand Down Expand Up @@ -205,16 +228,21 @@ export const JAVA_DEFAULT_CLASS_PRESET: ClassPresetType<JavaOptions> = {
const setterName = FormatHelpers.toPascalCase(property.propertyName);

if (model.options.isExtended) {
// don't render setters for discriminator, dictionary properties, or enums (because they can be set to constants in the models that extend them)
if (isDiscriminatorOrDictionary(model, property) || isEnum(property)) {
// don't render setters for discriminator, dictionary properties, or enums that are not set with a const value
if (
isDiscriminatorOrDictionary(model, property) ||
isEnumImplementedByConstValue(model, property)
) {
return '';
}

return `public void set${setterName}(${property.property.type} ${property.propertyName});`;
}

// don't render override for enums because enum setters in the interfaces are not rendered
const override = !isEnum(property) ? getOverride(model, property) : '';
// don't render override for enums that are not set with a const value
const override = !isEnumImplementedByConstValue(model, property)
? getOverride(model, property)
: '';

return `${override}public void set${setterName}(${property.property.type} ${property.propertyName}) { this.${property.propertyName} = ${property.propertyName}; }`;
}
Expand Down
1 change: 1 addition & 0 deletions src/models/ConstrainedMetaModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class ConstrainedMetaModelOptions extends MetaModelOptions {
discriminator?: ConstrainedMetaModelOptionsDiscriminator;
parents?: ConstrainedMetaModel[];
extend?: ConstrainedMetaModel[];
implementedBy?: ConstrainedMetaModel[];
}

export interface GetNearestDependenciesArgument {
Expand Down
10 changes: 5 additions & 5 deletions test/generators/java/JavaGenerator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,10 @@ describe('JavaGenerator', () => {
type: 'string',
description: 'test'
},
sequencetype: {
sequence_type: {
title: 'CloudEvent.SequenceType',
type: 'string',
enum: ['Integer']
enum: ['Integer', 'StringTest']
}
},
required: ['id', 'type']
Expand All @@ -376,7 +376,7 @@ describe('JavaGenerator', () => {
title: 'Test',
type: 'object',
properties: {
testEnum: {
test_enum: {
title: 'TestEnum',
type: 'string',
enum: ['FOO', 'BAR']
Expand All @@ -390,10 +390,10 @@ describe('JavaGenerator', () => {
{
type: 'object',
properties: {
testEnum: {
test_enum: {
const: 'FOO'
},
testProp2: {
test_string: {
type: 'string'
}
}
Expand Down
51 changes: 27 additions & 24 deletions test/generators/java/__snapshots__/JavaGenerator.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public interface Pet {
@NotNull
@JsonProperty(\\"type\\")
private final CloudEventType type = CloudEventType.DOG;
@JsonProperty(\\"sequencetype\\")
@JsonProperty(\\"sequence_type\\")
@JsonInclude(JsonInclude.Include.NON_NULL)
private CloudEventDotSequenceType sequencetype;
private CloudEventDotSequenceType sequenceType;
@JsonProperty(\\"data\\")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String data;
Expand All @@ -40,8 +40,9 @@ public interface Pet {
public CloudEventType getType() { return this.type; }
@Override
public CloudEventDotSequenceType getSequencetype() { return this.sequencetype; }
public void setSequencetype(CloudEventDotSequenceType sequencetype) { this.sequencetype = sequencetype; }
public CloudEventDotSequenceType getSequenceType() { return this.sequenceType; }
@Override
public void setSequenceType(CloudEventDotSequenceType sequenceType) { this.sequenceType = sequenceType; }
public String getData() { return this.data; }
public void setData(String data) { this.data = data; }
Expand All @@ -64,23 +65,23 @@ public interface Pet {
return
Objects.equals(this.id, self.id) &&
Objects.equals(this.type, self.type) &&
Objects.equals(this.sequencetype, self.sequencetype) &&
Objects.equals(this.sequenceType, self.sequenceType) &&
Objects.equals(this.data, self.data) &&
Objects.equals(this.test, self.test) &&
Objects.equals(this.additionalProperties, self.additionalProperties);
}
@Override
public int hashCode() {
return Objects.hash((Object)id, (Object)type, (Object)sequencetype, (Object)data, (Object)test, (Object)additionalProperties);
return Objects.hash((Object)id, (Object)type, (Object)sequenceType, (Object)data, (Object)test, (Object)additionalProperties);
}
@Override
public String toString() {
return \\"class Dog {\\\\n\\" +
\\" id: \\" + toIndentedString(id) + \\"\\\\n\\" +
\\" type: \\" + toIndentedString(type) + \\"\\\\n\\" +
\\" sequencetype: \\" + toIndentedString(sequencetype) + \\"\\\\n\\" +
\\" sequenceType: \\" + toIndentedString(sequenceType) + \\"\\\\n\\" +
\\" data: \\" + toIndentedString(data) + \\"\\\\n\\" +
\\" test: \\" + toIndentedString(test) + \\"\\\\n\\" +
\\" additionalProperties: \\" + toIndentedString(additionalProperties) + \\"\\\\n\\" +
Expand Down Expand Up @@ -128,7 +129,7 @@ public interface Pet {
}
}",
"public enum CloudEventDotSequenceType {
INTEGER((String)\\"Integer\\");
INTEGER((String)\\"Integer\\"), STRING_TEST((String)\\"StringTest\\");
private String value;
Expand Down Expand Up @@ -157,20 +158,20 @@ public interface Pet {
}
}",
"public class TestAllOf implements Test {
@JsonProperty(\\"testEnum\\")
@JsonProperty(\\"test_enum\\")
@JsonInclude(JsonInclude.Include.NON_NULL)
private final TestEnum testEnum = TestEnum.FOO;
@JsonProperty(\\"testProp2\\")
@JsonProperty(\\"test_string\\")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String testProp2;
private String testString;
@JsonInclude(JsonInclude.Include.NON_NULL)
private Map<String, Object> additionalProperties;
@Override
public TestEnum getTestEnum() { return this.testEnum; }
public String getTestProp2() { return this.testProp2; }
public void setTestProp2(String testProp2) { this.testProp2 = testProp2; }
public String getTestString() { return this.testString; }
public void setTestString(String testString) { this.testString = testString; }
public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; }
public void setAdditionalProperties(Map<String, Object> additionalProperties) { this.additionalProperties = additionalProperties; }
Expand All @@ -186,20 +187,20 @@ public interface Pet {
TestAllOf self = (TestAllOf) o;
return
Objects.equals(this.testEnum, self.testEnum) &&
Objects.equals(this.testProp2, self.testProp2) &&
Objects.equals(this.testString, self.testString) &&
Objects.equals(this.additionalProperties, self.additionalProperties);
}
@Override
public int hashCode() {
return Objects.hash((Object)testEnum, (Object)testProp2, (Object)additionalProperties);
return Objects.hash((Object)testEnum, (Object)testString, (Object)additionalProperties);
}
@Override
public String toString() {
return \\"class TestAllOf {\\\\n\\" +
\\" testEnum: \\" + toIndentedString(testEnum) + \\"\\\\n\\" +
\\" testProp2: \\" + toIndentedString(testProp2) + \\"\\\\n\\" +
\\" testString: \\" + toIndentedString(testString) + \\"\\\\n\\" +
\\" additionalProperties: \\" + toIndentedString(additionalProperties) + \\"\\\\n\\" +
\\"}\\";
}
Expand Down Expand Up @@ -251,7 +252,8 @@ public interface Pet {
public String getId();
public void setId(String id);
public CloudEventDotSequenceType getSequencetype();
public CloudEventDotSequenceType getSequenceType();
public void setSequenceType(CloudEventDotSequenceType sequenceType);
}",
"public class Cat implements Pet, CloudEvent {
@NotNull
Expand All @@ -260,9 +262,9 @@ public interface Pet {
@NotNull
@JsonProperty(\\"type\\")
private final CloudEventType type = CloudEventType.CAT;
@JsonProperty(\\"sequencetype\\")
@JsonProperty(\\"sequence_type\\")
@JsonInclude(JsonInclude.Include.NON_NULL)
private CloudEventDotSequenceType sequencetype;
private CloudEventDotSequenceType sequenceType;
@JsonInclude(JsonInclude.Include.NON_NULL)
private Map<String, Object> additionalProperties;
Expand All @@ -274,8 +276,9 @@ public interface Pet {
public CloudEventType getType() { return this.type; }
@Override
public CloudEventDotSequenceType getSequencetype() { return this.sequencetype; }
public void setSequencetype(CloudEventDotSequenceType sequencetype) { this.sequencetype = sequencetype; }
public CloudEventDotSequenceType getSequenceType() { return this.sequenceType; }
@Override
public void setSequenceType(CloudEventDotSequenceType sequenceType) { this.sequenceType = sequenceType; }
public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; }
public void setAdditionalProperties(Map<String, Object> additionalProperties) { this.additionalProperties = additionalProperties; }
Expand All @@ -292,21 +295,21 @@ public interface Pet {
return
Objects.equals(this.id, self.id) &&
Objects.equals(this.type, self.type) &&
Objects.equals(this.sequencetype, self.sequencetype) &&
Objects.equals(this.sequenceType, self.sequenceType) &&
Objects.equals(this.additionalProperties, self.additionalProperties);
}
@Override
public int hashCode() {
return Objects.hash((Object)id, (Object)type, (Object)sequencetype, (Object)additionalProperties);
return Objects.hash((Object)id, (Object)type, (Object)sequenceType, (Object)additionalProperties);
}
@Override
public String toString() {
return \\"class Cat {\\\\n\\" +
\\" id: \\" + toIndentedString(id) + \\"\\\\n\\" +
\\" type: \\" + toIndentedString(type) + \\"\\\\n\\" +
\\" sequencetype: \\" + toIndentedString(sequencetype) + \\"\\\\n\\" +
\\" sequenceType: \\" + toIndentedString(sequenceType) + \\"\\\\n\\" +
\\" additionalProperties: \\" + toIndentedString(additionalProperties) + \\"\\\\n\\" +
\\"}\\";
}
Expand Down

0 comments on commit cc4e368

Please sign in to comment.