Skip to content

Commit f81e07b

Browse files
authored
Merge pull request #2163 from altro3/fix-interface-inheritance
Fix process interfaces with inheritance
2 parents 0987d92 + 987b816 commit f81e07b

File tree

3 files changed

+220
-92
lines changed

3 files changed

+220
-92
lines changed

openapi/src/main/java/io/micronaut/openapi/visitor/AbstractOpenApiEndpointVisitor.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@
172172
import static io.micronaut.openapi.visitor.SchemaUtils.getOperationOnPathItem;
173173
import static io.micronaut.openapi.visitor.SchemaUtils.getSchemaByRef;
174174
import static io.micronaut.openapi.visitor.SchemaUtils.setOperationOnPathItem;
175-
import static io.micronaut.openapi.visitor.SchemaUtils.setSpecVersion;
176175
import static io.micronaut.openapi.visitor.SecurityUtils.processSecuritySchemes;
177176
import static io.micronaut.openapi.visitor.SecurityUtils.readSecurityRequirements;
178177
import static io.micronaut.openapi.visitor.StringUtil.CLOSE_BRACE;

openapi/src/main/java/io/micronaut/openapi/visitor/SchemaUtils.java

Lines changed: 168 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363

6464
import java.io.IOException;
6565
import java.util.ArrayList;
66+
import java.util.Arrays;
6667
import java.util.Collection;
6768
import java.util.Collections;
6869
import java.util.HashMap;
@@ -658,97 +659,6 @@ public static Content mergeContent(Content c1, Content c2) {
658659
return c1;
659660
}
660661

661-
public static boolean isEquals(Schema<?> s1, Schema<?> s2) {
662-
if (s1 == s2) {
663-
return true;
664-
}
665-
if (s1 == null) {
666-
return false;
667-
}
668-
var t1 = s1.getType();
669-
if (t1 == null) {
670-
t1 = TYPE_OBJECT;
671-
}
672-
var t2 = s2.getType();
673-
if (t2 == null) {
674-
t2 = TYPE_OBJECT;
675-
}
676-
var types1 = s1.getTypes();
677-
if (types1 == null) {
678-
types1 = Set.of(TYPE_OBJECT);
679-
}
680-
var types2 = s2.getTypes();
681-
if (types2 == null) {
682-
types2 = Set.of(TYPE_OBJECT);
683-
}
684-
685-
return Objects.equals(t1, t2)
686-
&& Objects.equals(types1, types2)
687-
&& Objects.equals(s1.getTitle(), s2.getTitle())
688-
&& Objects.equals(s1.getMultipleOf(), s2.getMultipleOf())
689-
&& Objects.equals(s1.getMaximum(), s2.getMaximum())
690-
&& Objects.equals(s1.getExclusiveMaximum(), s2.getExclusiveMaximum())
691-
&& Objects.equals(s1.getExclusiveMaximumValue(), s2.getExclusiveMaximumValue())
692-
&& Objects.equals(s1.getMinimum(), s2.getMinimum())
693-
&& Objects.equals(s1.getExclusiveMinimum(), s2.getExclusiveMinimum())
694-
&& Objects.equals(s1.getExclusiveMinimumValue(), s2.getExclusiveMinimumValue())
695-
&& Objects.equals(s1.getMaxLength(), s2.getMaxLength())
696-
&& Objects.equals(s1.getMinLength(), s2.getMinLength())
697-
&& Objects.equals(s1.getPattern(), s2.getPattern())
698-
&& Objects.equals(s1.getMaxItems(), s2.getMaxItems())
699-
&& Objects.equals(s1.getMinItems(), s2.getMinItems())
700-
&& Objects.equals(s1.getUniqueItems(), s2.getUniqueItems())
701-
&& Objects.equals(s1.getMaxProperties(), s2.getMaxProperties())
702-
&& Objects.equals(s1.getMinProperties(), s2.getMinProperties())
703-
&& Objects.equals(s1.getRequired(), s2.getRequired())
704-
&& Objects.equals(s1.getNot(), s2.getNot())
705-
&& Objects.equals(s1.getProperties(), s2.getProperties())
706-
&& Objects.equals(s1.getAdditionalProperties(), s2.getAdditionalProperties())
707-
&& Objects.equals(s1.getDescription(), s2.getDescription())
708-
&& Objects.equals(s1.getFormat(), s2.getFormat())
709-
&& Objects.equals(s1.get$ref(), s2.get$ref())
710-
&& Objects.equals(s1.getNullable(), s2.getNullable())
711-
&& Objects.equals(s1.getReadOnly(), s2.getReadOnly())
712-
&& Objects.equals(s1.getWriteOnly(), s2.getWriteOnly())
713-
&& Objects.equals(s1.getExample(), s2.getExample())
714-
&& Objects.equals(s1.getExternalDocs(), s2.getExternalDocs())
715-
&& Objects.equals(s1.getDeprecated(), s2.getDeprecated())
716-
&& Objects.equals(s1.getXml(), s2.getXml())
717-
&& Objects.equals(s1.getExtensions(), s2.getExtensions())
718-
&& Objects.equals(s1.getDiscriminator(), s2.getDiscriminator())
719-
&& Objects.equals(s1.getEnum(), s2.getEnum())
720-
&& Objects.equals(s1.getContains(), s2.getContains())
721-
&& Objects.equals(s1.getPatternProperties(), s2.getPatternProperties())
722-
&& Objects.equals(s1.get$id(), s2.get$id())
723-
&& Objects.equals(s1.get$anchor(), s2.get$anchor())
724-
&& Objects.equals(s1.get$schema(), s2.get$schema())
725-
&& Objects.equals(s1.get$vocabulary(), s2.get$vocabulary())
726-
&& Objects.equals(s1.get$dynamicAnchor(), s2.get$dynamicAnchor())
727-
&& Objects.equals(s1.getAllOf(), s2.getAllOf())
728-
&& Objects.equals(s1.getAnyOf(), s2.getAnyOf())
729-
&& Objects.equals(s1.getOneOf(), s2.getOneOf())
730-
&& Objects.equals(s1.getConst(), s2.getConst())
731-
&& Objects.equals(s1.getDefault(), s2.getDefault())
732-
&& Objects.equals(s1.getContentEncoding(), s2.getContentEncoding())
733-
&& Objects.equals(s1.getContentMediaType(), s2.getContentMediaType())
734-
&& Objects.equals(s1.getContentSchema(), s2.getContentSchema())
735-
&& Objects.equals(s1.getPropertyNames(), s2.getPropertyNames())
736-
&& Objects.equals(s1.getUnevaluatedProperties(), s2.getUnevaluatedProperties())
737-
&& Objects.equals(s1.getMaxContains(), s2.getMaxContains())
738-
&& Objects.equals(s1.getMinContains(), s2.getMinContains())
739-
&& Objects.equals(s1.getAdditionalItems(), s2.getAdditionalItems())
740-
&& Objects.equals(s1.getUnevaluatedItems(), s2.getUnevaluatedItems())
741-
&& Objects.equals(s1.getIf(), s2.getIf())
742-
&& Objects.equals(s1.getElse(), s2.getElse())
743-
&& Objects.equals(s1.getThen(), s2.getThen())
744-
&& Objects.equals(s1.getDependentRequired(), s2.getDependentRequired())
745-
&& Objects.equals(s1.getDependentSchemas(), s2.getDependentSchemas())
746-
&& Objects.equals(s1.get$comment(), s2.get$comment())
747-
&& Objects.equals(s1.getExamples(), s2.getExamples())
748-
&& Objects.equals(s1.getPrefixItems(), s2.getPrefixItems())
749-
&& Objects.equals(s1.getItems(), s2.getItems());
750-
}
751-
752662
public static Schema<?> mergeSchema(Schema<?> s1, Schema<?> s2) {
753663
if (s1 == null) {
754664
return s2;
@@ -1628,4 +1538,171 @@ public static Schema<?> getSchemaByRef(String schemaRef, OpenAPI openApi) {
16281538
}
16291539
return resolveSchemas(openApi).get(schemaRef.substring(COMPONENTS_SCHEMAS_PREFIX.length()));
16301540
}
1541+
1542+
public static boolean isEquals(Schema<?> s1, Schema<?> s2) {
1543+
if (s1 == s2) {
1544+
return true;
1545+
}
1546+
if (s1 == null) {
1547+
return false;
1548+
}
1549+
var t1 = s1.getType();
1550+
if (t1 == null) {
1551+
t1 = TYPE_OBJECT;
1552+
}
1553+
var t2 = s2.getType();
1554+
if (t2 == null) {
1555+
t2 = TYPE_OBJECT;
1556+
}
1557+
var types1 = s1.getTypes();
1558+
if (types1 == null) {
1559+
types1 = Set.of(TYPE_OBJECT);
1560+
}
1561+
var types2 = s2.getTypes();
1562+
if (types2 == null) {
1563+
types2 = Set.of(TYPE_OBJECT);
1564+
}
1565+
1566+
return Objects.equals(t1, t2)
1567+
&& Objects.equals(types1, types2)
1568+
&& Objects.equals(s1.getTitle(), s2.getTitle())
1569+
&& Objects.equals(s1.getMultipleOf(), s2.getMultipleOf())
1570+
&& Objects.equals(s1.getMaximum(), s2.getMaximum())
1571+
&& Objects.equals(s1.getExclusiveMaximum(), s2.getExclusiveMaximum())
1572+
&& Objects.equals(s1.getExclusiveMaximumValue(), s2.getExclusiveMaximumValue())
1573+
&& Objects.equals(s1.getMinimum(), s2.getMinimum())
1574+
&& Objects.equals(s1.getExclusiveMinimum(), s2.getExclusiveMinimum())
1575+
&& Objects.equals(s1.getExclusiveMinimumValue(), s2.getExclusiveMinimumValue())
1576+
&& Objects.equals(s1.getMaxLength(), s2.getMaxLength())
1577+
&& Objects.equals(s1.getMinLength(), s2.getMinLength())
1578+
&& Objects.equals(s1.getPattern(), s2.getPattern())
1579+
&& Objects.equals(s1.getMaxItems(), s2.getMaxItems())
1580+
&& Objects.equals(s1.getMinItems(), s2.getMinItems())
1581+
&& Objects.equals(s1.getUniqueItems(), s2.getUniqueItems())
1582+
&& Objects.equals(s1.getMaxProperties(), s2.getMaxProperties())
1583+
&& Objects.equals(s1.getMinProperties(), s2.getMinProperties())
1584+
&& Objects.equals(s1.getNot(), s2.getNot())
1585+
&& Objects.equals(s1.getAdditionalProperties(), s2.getAdditionalProperties())
1586+
&& Objects.equals(s1.getDescription(), s2.getDescription())
1587+
&& Objects.equals(s1.getFormat(), s2.getFormat())
1588+
&& Objects.equals(s1.get$ref(), s2.get$ref())
1589+
&& Objects.equals(s1.getNullable(), s2.getNullable())
1590+
&& Objects.equals(s1.getReadOnly(), s2.getReadOnly())
1591+
&& Objects.equals(s1.getWriteOnly(), s2.getWriteOnly())
1592+
&& isObjectsEqual(s1.getExample(), s2.getExample())
1593+
&& Objects.equals(s1.getExternalDocs(), s2.getExternalDocs())
1594+
&& Objects.equals(s1.getDeprecated(), s2.getDeprecated())
1595+
&& Objects.equals(s1.getXml(), s2.getXml())
1596+
&& Objects.equals(s1.getExtensions(), s2.getExtensions())
1597+
&& Objects.equals(s1.getDiscriminator(), s2.getDiscriminator())
1598+
&& Objects.equals(s1.getEnum(), s2.getEnum())
1599+
&& isEquals(s1.getContains(), s2.getContains())
1600+
&& isEquals(s1.getPatternProperties(), s2.getPatternProperties())
1601+
&& Objects.equals(s1.get$id(), s2.get$id())
1602+
&& Objects.equals(s1.get$anchor(), s2.get$anchor())
1603+
&& Objects.equals(s1.get$schema(), s2.get$schema())
1604+
&& Objects.equals(s1.get$vocabulary(), s2.get$vocabulary())
1605+
&& Objects.equals(s1.get$dynamicAnchor(), s2.get$dynamicAnchor())
1606+
&& isEquals(s1.getAllOf(), s2.getAllOf())
1607+
&& isEquals(s1.getAnyOf(), s2.getAnyOf())
1608+
&& isEquals(s1.getOneOf(), s2.getOneOf())
1609+
&& isObjectsEqual(s1.getConst(), s2.getConst())
1610+
&& isObjectsEqual(s1.getDefault(), s2.getDefault())
1611+
&& Objects.equals(s1.getContentEncoding(), s2.getContentEncoding())
1612+
&& Objects.equals(s1.getContentMediaType(), s2.getContentMediaType())
1613+
&& isEquals(s1.getContentSchema(), s2.getContentSchema())
1614+
&& isEquals(s1.getPropertyNames(), s2.getPropertyNames())
1615+
&& isEquals(s1.getUnevaluatedProperties(), s2.getUnevaluatedProperties())
1616+
&& Objects.equals(s1.getMaxContains(), s2.getMaxContains())
1617+
&& Objects.equals(s1.getMinContains(), s2.getMinContains())
1618+
&& isEquals(s1.getAdditionalItems(), s2.getAdditionalItems())
1619+
&& isEquals(s1.getUnevaluatedItems(), s2.getUnevaluatedItems())
1620+
&& isEquals(s1.getIf(), s2.getIf())
1621+
&& isEquals(s1.getElse(), s2.getElse())
1622+
&& isEquals(s1.getThen(), s2.getThen())
1623+
&& Objects.equals(s1.getDependentRequired(), s2.getDependentRequired())
1624+
&& isEquals(s1.getDependentSchemas(), s2.getDependentSchemas())
1625+
&& Objects.equals(s1.get$comment(), s2.get$comment())
1626+
&& isEqualsExamples(s1.getExamples(), s2.getExamples())
1627+
&& isEquals(s1.getPrefixItems(), s2.getPrefixItems())
1628+
&& isEquals(s1.getItems(), s2.getItems());
1629+
}
1630+
1631+
public static boolean isObjectsEqual(Object o1, Object o2) {
1632+
if (o1 == null) {
1633+
return o2 == null;
1634+
}
1635+
if (o2 == null) {
1636+
return false;
1637+
}
1638+
if (o1 instanceof Object[] a1 && o2 instanceof Object[] a2) {
1639+
return Arrays.equals(a1, a2);
1640+
}
1641+
return Objects.equals(o1, o2);
1642+
}
1643+
1644+
public static boolean isEquals(Map<String, Schema> m1, Map<String, Schema> m2) {
1645+
if (m1 == null) {
1646+
return m2 == null;
1647+
}
1648+
if (m2 == null) {
1649+
return false;
1650+
}
1651+
if (m1.size() != m2.size()) {
1652+
return false;
1653+
}
1654+
1655+
return m1.entrySet().stream()
1656+
.allMatch(e -> isEquals(e.getValue(), m2.get(e.getKey())));
1657+
}
1658+
1659+
public static boolean isEqualsExamples(List<?> l1, List<?> l2) {
1660+
if (l1 == null) {
1661+
return l2 == null;
1662+
}
1663+
if (l2 == null) {
1664+
return false;
1665+
}
1666+
if (l1.size() != l2.size()) {
1667+
return false;
1668+
}
1669+
for (var e1 : l1) {
1670+
boolean found = false;
1671+
for (var e2 : l2) {
1672+
if (isObjectsEqual(e1, e2)) {
1673+
found = true;
1674+
break;
1675+
}
1676+
}
1677+
if (!found) {
1678+
return false;
1679+
}
1680+
}
1681+
return true;
1682+
}
1683+
1684+
public static boolean isEquals(List<Schema> l1, List<Schema> l2) {
1685+
if (l1 == null) {
1686+
return l2 == null;
1687+
}
1688+
if (l2 == null) {
1689+
return false;
1690+
}
1691+
if (l1.size() != l2.size()) {
1692+
return false;
1693+
}
1694+
for (var s1 : l1) {
1695+
boolean found = false;
1696+
for (var s2 : l2) {
1697+
if (isEquals(s1, s2)) {
1698+
found = true;
1699+
break;
1700+
}
1701+
}
1702+
if (!found) {
1703+
return false;
1704+
}
1705+
}
1706+
return true;
1707+
}
16311708
}

openapi/src/test/groovy/io/micronaut/openapi/visitor/OpenApiControllerVisitorSpec.groovy

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3097,4 +3097,56 @@ class MyBean {}
30973097
openApi.components.schemas.containsKey("Response")
30983098
openApi.components.schemas.containsKey("Response_1")
30993099
}
3100+
3101+
void "test interfaces inheritance"() {
3102+
3103+
buildBeanDefinition('test.MyBean', '''
3104+
package test;
3105+
3106+
import io.micronaut.http.annotation.Controller;
3107+
import io.micronaut.http.annotation.Get;
3108+
import io.micronaut.http.annotation.Post;
3109+
import io.micronaut.http.annotation.QueryValue;
3110+
3111+
import java.util.List;
3112+
3113+
@Controller
3114+
interface MyController extends MyInterface<Integer> {
3115+
3116+
@Get
3117+
String get(
3118+
@QueryValue(defaultValue = "a") List<String> a,
3119+
@QueryValue(defaultValue = "b") List<String> b
3120+
);
3121+
}
3122+
3123+
interface MyInterface<T> {
3124+
@Post
3125+
String set(@QueryValue String arg1, @QueryValue T arg2);
3126+
}
3127+
3128+
@jakarta.inject.Singleton
3129+
class MyBean {}
3130+
''')
3131+
when:
3132+
Operation op1 = Utils.testReference?.paths?."/"?.get
3133+
Operation op2 = Utils.testReference?.paths?."/"?.post
3134+
3135+
then:
3136+
op1
3137+
op1.parameters[0].name == 'a'
3138+
op1.parameters[0].schema.type == 'array'
3139+
op1.parameters[0].schema.items.type == 'string'
3140+
3141+
op1.parameters[1].name == 'b'
3142+
op1.parameters[1].schema.type == 'array'
3143+
op1.parameters[1].schema.items.type == 'string'
3144+
3145+
op2
3146+
op2.parameters[0].name == 'arg1'
3147+
op2.parameters[0].schema.type == 'string'
3148+
3149+
op2.parameters[1].name == 'arg2'
3150+
op2.parameters[1].schema.type == 'integer'
3151+
}
31003152
}

0 commit comments

Comments
 (0)