Browse Source

added test checking DiscriminatorMapping for EntityId, some java docs

pull/15196/head
dashevchenko 3 months ago
parent
commit
89acce4c20
  1. 27
      application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java
  2. 50
      common/data/src/test/java/org/thingsboard/server/common/data/id/EntityIdTest.java

27
application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java

@ -446,11 +446,10 @@ public class SwaggerConfiguration {
});
// Deduplicate allOf child schemas: remove properties that are already defined
// in the referenced parent schema to avoid duplication (e.g. EntityId children)
schemas.values().forEach(schema -> deduplicateAllOfProperties(schema, schemas));
// Clean up internal marker extension used by deduplicateAllOfProperties
// in the referenced parent schema to avoid duplication (e.g. EntityId children),
// then clean up the internal marker extension used during deduplication.
schemas.values().forEach(schema -> {
deduplicateAllOfProperties(schema, schemas);
if (schema.getExtensions() != null) {
schema.getExtensions().remove("x-tb-own-props");
if (schema.getExtensions().isEmpty()) {
@ -845,6 +844,26 @@ public class SwaggerConfiguration {
return own;
}
/**
* Resolves the property ordering for a schema class.
*
* <p>Returns a list of JSON property names in the order they should appear in the
* OpenAPI schema. The caller uses this list to reorder the schema's property map;
* any properties <b>not</b> present in the returned list are appended alphabetically
* by the caller's {@code TreeMap} fallback, guaranteeing a stable, deterministic order.
*
* <p><b>Resolution strategy (first match wins):</b>
* <ol>
* <li>If {@code @JsonPropertyOrder} with an explicit {@code value()} is found on the
* class or any interface in its ancestry, that list is returned as-is. Note: if the
* annotation lists only a subset of fields, those fields are ordered first and the
* remaining properties fall through to the caller's alphabetical fallback consistent
* with Jackson's own behaviour for partial {@code @JsonPropertyOrder}.</li>
* <li>Otherwise, field-backed properties are returned in declaration order (superclass
* fields first). Getter-only properties are intentionally excluded to avoid
* non-deterministic ordering across restarts.</li>
* </ol>
*/
private static List<String> resolvePropertyOrder(Class<?> cls, com.fasterxml.jackson.databind.BeanDescription beanDesc) {
// If an explicit @JsonPropertyOrder is present on the class or any interface in its
// ancestry, honour it directly. Walk up the class hierarchy; for each class also walk

50
common/data/src/test/java/org/thingsboard/server/common/data/id/EntityIdTest.java

@ -15,8 +15,18 @@
*/
package org.thingsboard.server.common.data.id;
import io.swagger.v3.oas.annotations.media.DiscriminatorMapping;
import io.swagger.v3.oas.annotations.media.Schema;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.thingsboard.server.common.data.EntityType;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
public class EntityIdTest {
@ -25,4 +35,44 @@ public class EntityIdTest {
Assertions.assertEquals("13814000-1dd2-11b2-8080-808080808080", EntityId.NULL_UUID.toString());
}
@Test
public void allEntityIdImplementors_shouldBeInDiscriminatorMapping() {
Schema schemaAnnotation = EntityId.class.getAnnotation(Schema.class);
assertThat(schemaAnnotation).as("EntityId must have @Schema annotation").isNotNull();
DiscriminatorMapping[] mappings = schemaAnnotation.discriminatorMapping();
Map<String, Class<?>> discriminatorMap = Arrays.stream(mappings)
.collect(Collectors.toMap(DiscriminatorMapping::value, DiscriminatorMapping::schema));
UUID testUuid = UUID.randomUUID();
for (EntityType entityType : EntityType.values()) {
EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, testUuid);
String typeName = entityType.name();
assertThat(discriminatorMap)
.as("EntityId @Schema discriminatorMapping is missing entry for EntityType." + typeName)
.containsKey(typeName);
assertThat(discriminatorMap.get(typeName))
.as("Discriminator mapping for " + typeName + " should point to " + entityId.getClass().getSimpleName())
.isEqualTo(entityId.getClass());
}
}
@Test
public void allEntityIdImplementors_shouldHaveAllOfEntityId() {
UUID testUuid = UUID.randomUUID();
for (EntityType entityType : EntityType.values()) {
EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, testUuid);
Class<?> idClass = entityId.getClass();
Schema schemaAnnotation = idClass.getAnnotation(Schema.class);
assertThat(schemaAnnotation)
.as(idClass.getSimpleName() + " must have @Schema annotation")
.isNotNull();
assertThat(schemaAnnotation.allOf())
.as(idClass.getSimpleName() + " @Schema must include allOf = EntityId.class")
.contains(EntityId.class);
}
}
}
Loading…
Cancel
Save